Java Tutorial/Swing/Drag Drop

Материал из Java эксперт
Перейти к: навигация, поиск

Содержание

14. Basic drag and drop

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*

* BasicDnD.java requires no other files.
*/

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JCheckBox; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeSelectionModel; public class BasicDnD extends JPanel implements ActionListener {

 private static JFrame frame;
 private JTextArea textArea;
 private JTextField textField;
 private JList list;
 private JTable table;
 private JTree tree;
 private JColorChooser colorChooser;
 private JCheckBox toggleDnD;
 public BasicDnD() {
   super(new BorderLayout());
   JPanel leftPanel = createVerticalBoxPanel();
   JPanel rightPanel = createVerticalBoxPanel();
   // Create a table model.
   DefaultTableModel tm = new DefaultTableModel();
   tm.addColumn("Column 0");
   tm.addColumn("Column 1");
   tm.addColumn("Column 2");
   tm.addColumn("Column 3");
   tm.addRow(new String[] { "Table 00", "Table 01", "Table 02", "Table 03" });
   tm.addRow(new String[] { "Table 10", "Table 11", "Table 12", "Table 13" });
   tm.addRow(new String[] { "Table 20", "Table 21", "Table 22", "Table 23" });
   tm.addRow(new String[] { "Table 30", "Table 31", "Table 32", "Table 33" });
   // LEFT COLUMN
   // Use the table model to create a table.
   table = new JTable(tm);
   leftPanel.add(createPanelForComponent(table, "JTable"));
   // Create a color chooser.
   colorChooser = new JColorChooser();
   leftPanel.add(createPanelForComponent(colorChooser, "JColorChooser"));
   // RIGHT COLUMN
   // Create a textfield.
   textField = new JTextField(30);
   textField.setText("Favorite foods:\nPizza, Moussaka, Pot roast");
   rightPanel.add(createPanelForComponent(textField, "JTextField"));
   // Create a scrolled text area.
   textArea = new JTextArea(5, 30);
   textArea.setText("Favorite shows:\nBuffy, Alias, Angel");
   JScrollPane scrollPane = new JScrollPane(textArea);
   rightPanel.add(createPanelForComponent(scrollPane, "JTextArea"));
   // Create a list model and a list.
   DefaultListModel listModel = new DefaultListModel();
   listModel.addElement("Martha Washington");
   listModel.addElement("Abigail Adams");
   listModel.addElement("Martha Randolph");
   listModel.addElement("Dolley Madison");
   listModel.addElement("Elizabeth Monroe");
   listModel.addElement("Louisa Adams");
   listModel.addElement("Emily Donelson");
   list = new JList(listModel);
   list.setVisibleRowCount(-1);
   list.getSelectionModel().setSelectionMode(
       ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
   list.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport info) {
       // we only import Strings
       if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
       if (dl.getIndex() == -1) {
         return false;
       }
       return true;
     }
     public boolean importData(TransferHandler.TransferSupport info) {
       if (!info.isDrop()) {
         return false;
       }
       // Check for String flavor
       if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         displayDropLocation("List doesn"t accept a drop of this type.");
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
       DefaultListModel listModel = (DefaultListModel) list.getModel();
       int index = dl.getIndex();
       boolean insert = dl.isInsert();
       // Get the current string under the drop.
       String value = (String) listModel.getElementAt(index);
       // Get the string that is being dropped.
       Transferable t = info.getTransferable();
       String data;
       try {
         data = (String) t.getTransferData(DataFlavor.stringFlavor);
       } catch (Exception e) {
         return false;
       }
       // Display a dialog with the drop information.
       String dropValue = "\"" + data + "\" dropped ";
       if (dl.isInsert()) {
         if (dl.getIndex() == 0) {
           displayDropLocation(dropValue + "at beginning of list");
         } else if (dl.getIndex() >= list.getModel().getSize()) {
           displayDropLocation(dropValue + "at end of list");
         } else {
           String value1 = (String) list.getModel().getElementAt(
               dl.getIndex() - 1);
           String value2 = (String) list.getModel()
               .getElementAt(dl.getIndex());
           displayDropLocation(dropValue + "between \"" + value1 + "\" and \""
               + value2 + "\"");
         }
       } else {
         displayDropLocation(dropValue + "on top of " + "\"" + value + "\"");
       }
       /**
        * This is commented out for the basicdemo.html tutorial page. * If you
        * add this code snippet back and delete the * "return false;" line, the
        * list will accept drops * of type string. // Perform the actual
        * import. if (insert) { listModel.add(index, data); } else {
        * listModel.set(index, data); } return true;
        */
       return false;
     }
     public int getSourceActions(JComponent c) {
       return COPY;
     }
     protected Transferable createTransferable(JComponent c) {
       JList list = (JList) c;
       Object[] values = list.getSelectedValues();
       StringBuffer buff = new StringBuffer();
       for (int i = 0; i < values.length; i++) {
         Object val = values[i];
         buff.append(val == null ? "" : val.toString());
         if (i != values.length - 1) {
           buff.append("\n");
         }
       }
       return new StringSelection(buff.toString());
     }
   });
   list.setDropMode(DropMode.ON_OR_INSERT);
   JScrollPane listView = new JScrollPane(list);
   listView.setPreferredSize(new Dimension(300, 100));
   rightPanel.add(createPanelForComponent(listView, "JList"));
   // Create a tree.
   DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Mia Familia");
   DefaultMutableTreeNode sharon = new DefaultMutableTreeNode("Sharon");
   rootNode.add(sharon);
   DefaultMutableTreeNode maya = new DefaultMutableTreeNode("Maya");
   sharon.add(maya);
   DefaultMutableTreeNode anya = new DefaultMutableTreeNode("Anya");
   sharon.add(anya);
   sharon.add(new DefaultMutableTreeNode("Bongo"));
   maya.add(new DefaultMutableTreeNode("Muffin"));
   anya.add(new DefaultMutableTreeNode("Winky"));
   DefaultTreeModel model = new DefaultTreeModel(rootNode);
   tree = new JTree(model);
   tree.getSelectionModel().setSelectionMode(
       TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
   JScrollPane treeView = new JScrollPane(tree);
   treeView.setPreferredSize(new Dimension(300, 100));
   rightPanel.add(createPanelForComponent(treeView, "JTree"));
   // Create the toggle button.
   toggleDnD = new JCheckBox("Turn on Drag and Drop");
   toggleDnD.setActionCommand("toggleDnD");
   toggleDnD.addActionListener(this);
   JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
       leftPanel, rightPanel);
   splitPane.setOneTouchExpandable(true);
   add(splitPane, BorderLayout.CENTER);
   add(toggleDnD, BorderLayout.PAGE_END);
   setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
 }
 protected JPanel createVerticalBoxPanel() {
   JPanel p = new JPanel();
   p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
   p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
   return p;
 }
 public JPanel createPanelForComponent(JComponent comp, String title) {
   JPanel panel = new JPanel(new BorderLayout());
   panel.add(comp, BorderLayout.CENTER);
   if (title != null) {
     panel.setBorder(BorderFactory.createTitledBorder(title));
   }
   return panel;
 }
 private void displayDropLocation(final String string) {
   SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       JOptionPane.showMessageDialog(null, string);
     }
   });
 }
 public void actionPerformed(ActionEvent e) {
   if ("toggleDnD".equals(e.getActionCommand())) {
     boolean toggle = toggleDnD.isSelected();
     textArea.setDragEnabled(toggle);
     textField.setDragEnabled(toggle);
     list.setDragEnabled(toggle);
     table.setDragEnabled(toggle);
     tree.setDragEnabled(toggle);
     colorChooser.setDragEnabled(toggle);
   }
 }
 /**
  * Create the GUI and show it. For thread safety, this method should be
  * invoked from the event-dispatching thread.
  */
 private static void createAndShowGUI() {
   // Create and set up the window.
   frame = new JFrame("BasicDnD");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   // Create and set up the content pane.
   JComponent newContentPane = new BasicDnD();
   newContentPane.setOpaque(true); // content panes must be opaque
   frame.setContentPane(newContentPane);
   // Display the window.
   frame.pack();
   frame.setVisible(true);
 }
 public static void main(String[] args) {
   // Schedule a job for the event-dispatching thread:
   // creating and showing this application"s GUI.
   javax.swing.SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       // Turn off metal"s use of bold fonts
       UIManager.put("swing.boldMetal", Boolean.FALSE);
       createAndShowGUI();
     }
   });
 }

}</source>





14. Built-in drag and drop support: utilize a TransferHandler class

   <source lang="java">

import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.TransferHandler; public class SimpleDnD {

 public static void main(String[] args) {
   JTextField field = new JTextField(10);
   JButton button = new JButton("Button");
   JFrame f = new JFrame();
   f.setTitle("Simple Drag & Drop");
   f.setLayout(new FlowLayout());
   f.add(button);
   f.add(field);
   field.setDragEnabled(true);
   button.setTransferHandler(new TransferHandler("text"));
   f.setSize(330, 150);
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   f.setLocationRelativeTo(null);
   f.setVisible(true);
 }

}</source>





14. Choose Drop Action

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; public class ChooseDropActionDemo extends JFrame {

 DefaultListModel from = new DefaultListModel();
 DefaultListModel copy = new DefaultListModel();
 DefaultListModel move = new DefaultListModel();
 JList dragFrom;
 public ChooseDropActionDemo() {
   super("ChooseDropActionDemo");
   for (int i = 15; i >= 0; i--) {
     from.add(0, "Source item " + i);
   }
   for (int i = 2; i >= 0; i--) {
     copy.add(0, "Target item " + i);
     move.add(0, "Target item " + i);
   }
   JPanel p = new JPanel();
   p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
   dragFrom = new JList(from);
   dragFrom.setTransferHandler(new FromTransferHandler());
   dragFrom.setPrototypeCellValue("List Item WWWWWW");
   dragFrom.setDragEnabled(true);
   dragFrom.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
   JLabel label = new JLabel("Drag from here:");
   label.setAlignmentX(0f);
   p.add(label);
   JScrollPane sp = new JScrollPane(dragFrom);
   sp.setAlignmentX(0f);
   p.add(sp);
   add(p, BorderLayout.WEST);
   JList moveTo = new JList(move);
   moveTo.setTransferHandler(new ToTransferHandler(TransferHandler.COPY));
   moveTo.setDropMode(DropMode.INSERT);
   JList copyTo = new JList(copy);
   copyTo.setTransferHandler(new ToTransferHandler(TransferHandler.MOVE));
   copyTo.setDropMode(DropMode.INSERT);
   p = new JPanel();
   p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
   label = new JLabel("Drop to COPY to here:");
   ;
   label.setAlignmentX(0f);
   p.add(label);
   sp = new JScrollPane(moveTo);
   sp.setAlignmentX(0f);
   p.add(sp);
   label = new JLabel("Drop to MOVE to here:");
   label.setAlignmentX(0f);
   p.add(label);
   sp = new JScrollPane(copyTo);
   sp.setAlignmentX(0f);
   p.add(sp);
   p.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
   add(p, BorderLayout.CENTER);
   ((JPanel) getContentPane()).setBorder(BorderFactory.createEmptyBorder(2, 2,
       2, 2));
   getContentPane().setPreferredSize(new Dimension(320, 315));
 }
 private static void createAndShowGUI() {
   // Create and set up the window.
   ChooseDropActionDemo test = new ChooseDropActionDemo();
   test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   // Display the window.
   test.pack();
   test.setVisible(true);
 }
 public static void main(String[] args) {
   SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       // Turn off metal"s use of bold fonts
       UIManager.put("swing.boldMetal", Boolean.FALSE);
       createAndShowGUI();
     }
   });
 }
 class FromTransferHandler extends TransferHandler {
   public int getSourceActions(JComponent comp) {
     return COPY_OR_MOVE;
   }
   private int index = 0;
   public Transferable createTransferable(JComponent comp) {
     index = dragFrom.getSelectedIndex();
     if (index < 0 || index >= from.getSize()) {
       return null;
     }
     return new StringSelection((String) dragFrom.getSelectedValue());
   }
   public void exportDone(JComponent comp, Transferable trans, int action) {
     if (action != MOVE) {
       return;
     }
     from.removeElementAt(index);
   }
 }
 class ToTransferHandler extends TransferHandler {
   int action;
   public ToTransferHandler(int action) {
     this.action = action;
   }
   public boolean canImport(TransferHandler.TransferSupport support) {
     // for the demo, we"ll only support drops (not clipboard paste)
     if (!support.isDrop()) {
       return false;
     }
     // we only import Strings
     if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
       return false;
     }
     boolean actionSupported = (action & support.getSourceDropActions()) == action;
     if (actionSupported) {
       support.setDropAction(action);
       return true;
     }
     return false;
   }
   public boolean importData(TransferHandler.TransferSupport support) {
     // if we can"t handle the import, say so
     if (!canImport(support)) {
       return false;
     }
     // fetch the drop location
     JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
     int index = dl.getIndex();
     // fetch the data and bail if this fails
     String data;
     try {
       data = (String) support.getTransferable().getTransferData(
           DataFlavor.stringFlavor);
     } catch (UnsupportedFlavorException e) {
       return false;
     } catch (java.io.IOException e) {
       return false;
     }
     JList list = (JList) support.getComponent();
     DefaultListModel model = (DefaultListModel) list.getModel();
     model.insertElementAt(data, index);
     Rectangle rect = list.getCellBounds(index, index);
     list.scrollRectToVisible(rect);
     list.setSelectedIndex(index);
     list.requestFocusInWindow();
     return true;
   }
 }

}</source>





14. Create a drag source a drop target and a transferable object.

   <source lang="java">

import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetAdapter; import java.awt.dnd.DropTargetDropEvent; import javax.swing.JFrame; import javax.swing.JPanel; public class ComplexExample extends JFrame implements DragGestureListener {

 public ComplexExample() {
   JPanel left = new JPanel();
   left.setBackground(Color.red);
   JPanel right = new JPanel();
   right.setBackground(Color.white);
   new MyDropTargetListener(right);
   DragSource ds = new DragSource();
   ds.createDefaultDragGestureRecognizer(left, DnDConstants.ACTION_COPY, this);
   setLayout(new FlowLayout());
   add(left);
   add(right);
   setSize(40,50);
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   setLocationRelativeTo(null);
   setVisible(true);
 }
 public void dragGestureRecognized(DragGestureEvent event) {
   Cursor cursor = null;
   JPanel panel = (JPanel) event.getComponent();
   Color color = panel.getBackground();
   if (event.getDragAction() == DnDConstants.ACTION_COPY) {
     cursor = DragSource.DefaultCopyDrop;
   }
   event.startDrag(cursor, new TransferableColor(color));
 }
 class MyDropTargetListener extends DropTargetAdapter {
   private DropTarget dropTarget;
   private JPanel panel;
   public MyDropTargetListener(JPanel panel) {
     this.panel = panel;
     dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this, true, null);
   }
   public void drop(DropTargetDropEvent event) {
     try {
       Transferable tr = event.getTransferable();
       Color color = (Color) tr.getTransferData(TransferableColor.colorFlavor);
       if (event.isDataFlavorSupported(TransferableColor.colorFlavor)) {
         event.acceptDrop(DnDConstants.ACTION_COPY);
         this.panel.setBackground(color);
         event.dropComplete(true);
         return;
       }
       event.rejectDrop();
     } catch (Exception e) {
       e.printStackTrace();
       event.rejectDrop();
     }
   }
 }
 public static void main(String[] args) {
   new ComplexExample();
 }

} class TransferableColor implements Transferable {

 protected static DataFlavor colorFlavor = new DataFlavor(Color.class, "A Color Object");
 protected static DataFlavor[] supportedFlavors = { colorFlavor };
 Color color;
 public TransferableColor(Color color) {
   this.color = color;
 }
 public DataFlavor[] getTransferDataFlavors() {
   return supportedFlavors;
 }
 public boolean isDataFlavorSupported(DataFlavor flavor) {
   if (flavor.equals(colorFlavor) || flavor.equals(DataFlavor.stringFlavor))
     return true;
   return false;
 }
 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
   if (flavor.equals(colorFlavor))
     return color;
   else if (flavor.equals(DataFlavor.stringFlavor))
     return color.toString();
   else
     throw new UnsupportedFlavorException(flavor);
 }

}</source>





14. Demonstrates how to add copy and drag support to a Swing component with TransferHandler

   <source lang="java">

/*

* Copyright (c) 2004 David Flanagan.  All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book, 
* please visit http://www.davidflanagan.ru/javaexamples3.
*/

import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.text.DateFormat; import java.util.Date; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JLabel; import javax.swing.KeyStroke; import javax.swing.Timer; import javax.swing.TransferHandler; import javax.swing.border.LineBorder; /**

* A custom Swing component that displays a simple digital clock. Demonstrates
* how to add copy and drag support to a Swing component with TransferHandler.
*/

public class DigitalClock extends JLabel {

 DateFormat format; // How to display the time in string form
 int updateFrequency; // How often to update the time (in milliseconds)
 Timer timer; // Triggers repeated updates to the clock
 public DigitalClock() {
   // Set default values for our properties
   setFormat(DateFormat.getTimeInstance(DateFormat.MEDIUM, getLocale()));
   setUpdateFrequency(1000); // Update once a second
   // Specify a Swing TransferHandler object to do the dirty work of
   // copy-and-paste and drag-and-drop for us. This one will transfer
   // the value of the "time" property. Since this property is read-only
   // it will allow drags but not drops.
   setTransferHandler(new TransferHandler("time"));
   // Since JLabel does not normally support drag-and-drop, we need an
   // event handler to detect a drag and start the transfer.
   addMouseMotionListener(new MouseMotionAdapter() {
     public void mouseDragged(MouseEvent e) {
       getTransferHandler().exportAsDrag(DigitalClock.this, e, TransferHandler.COPY);
     }
   });
   // Before we can have a keyboard binding for a Copy command,
   // the component needs to be able to accept keyboard focus.
   setFocusable(true);
   // Request focus when we"re clicked on
   addMouseListener(new MouseAdapter() {
     public void mouseClicked(MouseEvent e) {
       requestFocus();
     }
   });
   // Use a LineBorder to indicate when we"ve got the keyboard focus
   addFocusListener(new FocusListener() {
     public void focusGained(FocusEvent e) {
       setBorder(LineBorder.createBlackLineBorder());
     }
     public void focusLost(FocusEvent e) {
       setBorder(null);
     }
   });
   // Now bind the Ctrl-C keystroke to a "Copy" command.
   InputMap im = new InputMap();
   im.setParent(getInputMap(WHEN_FOCUSED));
   im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK), "Copy");
   setInputMap(WHEN_FOCUSED, im);
   // And bind the "Copy" command to a pre-defined Action that performs
   // a copy using the TransferHandler we"ve installed.
   ActionMap am = new ActionMap();
   am.setParent(getActionMap());
   am.put("Copy", TransferHandler.getCopyAction());
   setActionMap(am);
   // Create a javax.swing.Timer object that will generate ActionEvents
   // to tell us when to update the displayed time. Every updateFrequency
   // milliseconds, this timer will cause the actionPerformed() method
   // to be invoked. (For non-GUI applications, see java.util.Timer.)
   timer = new Timer(updateFrequency, new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       setText(getTime()); // set label to current time string
     }
   });
   timer.setInitialDelay(0); // Do the first update immediately
   timer.start(); // Start timing now!
 }
 // Return the current time as a String.
 // This is the property accessor method used by the TransferHandler.
 // Since there is a getter, but no setter, the TransferHandler will
 // reject any attempts to drop data on us.
 public String getTime() {
   // Use the DateFormat object to convert current time to a string
   return format.format(new Date());
 }
 // Here are two related property setter methods
 public void setFormat(DateFormat format) {
   this.format = format;
 }
 public void setUpdateFrequency(int ms) {
   this.updateFrequency = ms;
 }

}</source>





14. Demonstration of the top-level TransferHandler support on JFrame

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ 

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.awt.datatransfer.*; import java.awt.dnd.*; import java.util.*; /**

* Demonstration of the top-level {@code TransferHandler}
* support on {@code JFrame}.
*
* @author Shannon Hickey
*/

public class TopLevelTransferHandlerDemo extends JFrame {

   private static boolean DEMO = false;
   private JDesktopPane dp = new JDesktopPane();
   private DefaultListModel listModel = new DefaultListModel();
   private JList list = new JList(listModel);
   private static int left;
   private static int top;
   private JCheckBoxMenuItem copyItem;
   private JCheckBoxMenuItem nullItem;
   private JCheckBoxMenuItem thItem;
   private class Doc extends InternalFrameAdapter implements ActionListener {
       String name;
       JInternalFrame frame;
       TransferHandler th;
       JTextArea area;
       public Doc(File file) {
           this.name = file.getName();
           try {
               init(file.toURI().toURL());
           } catch (MalformedURLException e) {
               e.printStackTrace();
           }
       }
       
       public Doc(String name) {
           this.name = name;
           init(getClass().getResource(name));
       }
       
       private void init(URL url) {
           frame = new JInternalFrame(name);
           frame.addInternalFrameListener(this);
           listModel.add(listModel.size(), this);
           area = new JTextArea();
           area.setMargin(new Insets(5, 5, 5, 5));
           try {
               BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
               String in;
               while ((in = reader.readLine()) != null) {
                   area.append(in);
                   area.append("\n");
               }
               reader.close();
           } catch (Exception e) {
               e.printStackTrace();
               return;
           }
           th = area.getTransferHandler();
           area.setFont(new Font("monospaced", Font.PLAIN, 12));
           area.setCaretPosition(0);
           area.setDragEnabled(true);
           area.setDropMode(DropMode.INSERT);
           frame.getContentPane().add(new JScrollPane(area));
           dp.add(frame);
           frame.show();
           if (DEMO) {
               frame.setSize(300, 200);
           } else {
               frame.setSize(400, 300);
           }
           frame.setResizable(true);
           frame.setClosable(true);
           frame.setIconifiable(true);
           frame.setMaximizable(true);
           frame.setLocation(left, top);
           incr();
           SwingUtilities.invokeLater(new Runnable() {
               public void run() {
                   select();
               }
           });
           nullItem.addActionListener(this);
           setNullTH();
       }
       public void internalFrameClosing(InternalFrameEvent event) {
           listModel.removeElement(this);
           nullItem.removeActionListener(this);
       }
       public void internalFrameOpened(InternalFrameEvent event) {
           int index = listModel.indexOf(this);
           list.getSelectionModel().setSelectionInterval(index, index);
       }
       public void internalFrameActivated(InternalFrameEvent event) {
           int index = listModel.indexOf(this);
           list.getSelectionModel().setSelectionInterval(index, index);
       }
       public String toString() {
           return name;
       }
       
       public void select() {
           try {
               frame.toFront();
               frame.setSelected(true);
           } catch (java.beans.PropertyVetoException e) {}
       }
       
       public void actionPerformed(ActionEvent ae) {
           setNullTH();
       }
       
       public void setNullTH() {
           if (nullItem.isSelected()) {
               area.setTransferHandler(null);
           } else {
               area.setTransferHandler(th);
           }
       }
   }
   private TransferHandler handler = new TransferHandler() {
       public boolean canImport(TransferHandler.TransferSupport support) {
           if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
               return false;
           }
           if (copyItem.isSelected()) {
               boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;
               if (!copySupported) {
                   return false;
               }
               support.setDropAction(COPY);
           }
           return true;
       }
       public boolean importData(TransferHandler.TransferSupport support) {
           if (!canImport(support)) {
               return false;
           }
           
           Transferable t = support.getTransferable();
           try {
               java.util.List<File> l =
                   (java.util.List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
               for (File f : l) {
                   new Doc(f);
               }
           } catch (UnsupportedFlavorException e) {
               return false;
           } catch (IOException e) {
               return false;
           }
           return true;
       }
   };
   private static void incr() {
       left += 30;
       top += 30;
       if (top == 150) {
           top = 0;
       }
   }
   public TopLevelTransferHandlerDemo() {
       super("TopLevelTransferHandlerDemo");
       setJMenuBar(createDummyMenuBar());
       getContentPane().add(createDummyToolBar(), BorderLayout.NORTH);
       JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, list, dp);
       sp.setDividerLocation(120);
       getContentPane().add(sp);
       //new Doc("sample.txt");
       //new Doc("sample.txt");
       //new Doc("sample.txt");
       list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
       list.addListSelectionListener(new ListSelectionListener() {
           public void valueChanged(ListSelectionEvent e) {
               if (e.getValueIsAdjusting()) {
                   return;
               }
               
               Doc val = (Doc)list.getSelectedValue();
               if (val != null) {
                   val.select();
               }
            }
       });
       
       final TransferHandler th = list.getTransferHandler();
       nullItem.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent ae) {
               if (nullItem.isSelected()) {
                   list.setTransferHandler(null);
               } else {
                   list.setTransferHandler(th);
               }
           }
       });
       thItem.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent ae) {
               if (thItem.isSelected()) {
                   setTransferHandler(handler);
               } else {
                   setTransferHandler(null);
               }
           }
       });
       dp.setTransferHandler(handler);
   }
   private static void createAndShowGUI(String[] args) {
       try {
           UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
       } catch (Exception e) {
       }
       TopLevelTransferHandlerDemo test = new TopLevelTransferHandlerDemo();
       test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       if (DEMO) {
           test.setSize(493, 307);
       } else {
           test.setSize(800, 600);
       }
       test.setLocationRelativeTo(null);
       test.setVisible(true);
       test.list.requestFocus();
   }
   
   public static void main(final String[] args) {
       SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               //Turn off metal"s use of bold fonts
           UIManager.put("swing.boldMetal", Boolean.FALSE);
               createAndShowGUI(args);
           }
       });
   }
   
   private JToolBar createDummyToolBar() {
       JToolBar tb = new JToolBar();
       JButton b;
       b = new JButton("New");
       b.setRequestFocusEnabled(false);
       tb.add(b);
       b = new JButton("Open");
       b.setRequestFocusEnabled(false);
       tb.add(b);
       b = new JButton("Save");
       b.setRequestFocusEnabled(false);
       tb.add(b);
       b = new JButton("Print");
       b.setRequestFocusEnabled(false);
       tb.add(b);
       b = new JButton("Preview");
       b.setRequestFocusEnabled(false);
       tb.add(b);
       tb.setFloatable(false);
       return tb;
   }
   
   private JMenuBar createDummyMenuBar() {
       JMenuBar mb = new JMenuBar();
       mb.add(createDummyMenu("File"));
       mb.add(createDummyMenu("Edit"));
       mb.add(createDummyMenu("Search"));
       mb.add(createDummyMenu("View"));
       mb.add(createDummyMenu("Tools"));
       mb.add(createDummyMenu("Help"));
       
       JMenu demo = new JMenu("Demo");
       demo.setMnemonic(KeyEvent.VK_D);
       mb.add(demo);
       thItem = new JCheckBoxMenuItem("Use Top-Level TransferHandler");
       thItem.setMnemonic(KeyEvent.VK_T);
       demo.add(thItem);
       nullItem = new JCheckBoxMenuItem("Remove TransferHandler from List and Text");
       nullItem.setMnemonic(KeyEvent.VK_R);
       demo.add(nullItem);
       copyItem = new JCheckBoxMenuItem("Use COPY Action");
       copyItem.setMnemonic(KeyEvent.VK_C);
       demo.add(copyItem);
       return mb;
   }
   
   private JMenu createDummyMenu(String str) {
       JMenu menu = new JMenu(str);
       JMenuItem item = new JMenuItem("[Empty]");
       item.setEnabled(false);
       menu.add(item);
       return menu;
   }

}</source>





14. Detect a drag initiating gesture in your application

   <source lang="java">

import java.awt.BorderLayout; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragGestureRecognizer; import java.awt.dnd.DragSource; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; public class Main extends JFrame implements DragGestureListener {

 String[] items = { "Java", "C", "C++", "Lisp", "Perl", "Python" };
 DragSource ds = new DragSource();
 JList jl = new JList(items);
 public Main() {
   setSize(200, 150);
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
   getContentPane().add(new JScrollPane(jl), BorderLayout.CENTER);
   
   DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer(jl, DnDConstants.ACTION_COPY,
       this);
   setVisible(true);
 }
 public void dragGestureRecognized(DragGestureEvent dge) {
   System.out.println("Drag Gesture Recognized!");
 }
 public static void main(String args[]) {
   new Main();
 }

}</source>





14. DND Drag and drop List

   <source lang="java">

/**

* This is an example of a component, which serves as a DragSource as 
* well as Drop Target.
* To illustrate the concept, JList has been used as a droppable target
* and a draggable source.
* Any component can be used instead of a JList.
* The code also contains debugging messages which can be used for 
* diagnostics and understanding the flow of events.
* 
* @version 1.0
*/

import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.ListModel;

public class DNDList extends JList implements DropTargetListener, DragSourceListener, DragGestureListener {

 /**
  * enables this component to be a dropTarget
  */
 DropTarget dropTarget = null;
 /**
  * enables this component to be a Drag Source
  */
 DragSource dragSource = null;
 /**
  * constructor - initializes the DropTarget and DragSource.
  */
 public DNDList( ListModel dataModel )
 {
   super( dataModel );
   dropTarget = new DropTarget( this, this );
   dragSource = new DragSource();
   dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_MOVE, this );
 }
 /**
  * is invoked when you are dragging over the DropSite
  * 
  */
 public void dragEnter( DropTargetDragEvent event )
 {
   // debug messages for diagnostics
   System.out.println( "dragEnter" );
   event.acceptDrag( DnDConstants.ACTION_MOVE );
 }
 /**
  * is invoked when you are exit the DropSite without dropping
  * 
  */
 public void dragExit( DropTargetEvent event )
 {
   System.out.println( "dragExit" );
 }
 /**
  * is invoked when a drag operation is going on
  * 
  */
 public void dragOver( DropTargetDragEvent event )
 {
   System.out.println( "dragOver" );
 }
 /**
  * a drop has occurred
  * 
  */
 public void drop( DropTargetDropEvent event )
 {
   try
   {
     Transferable transferable = event.getTransferable();
     // we accept only Strings
     if( transferable.isDataFlavorSupported( DataFlavor.stringFlavor ) )
     {
       event.acceptDrop( DnDConstants.ACTION_MOVE );
       String s = ( String )transferable.getTransferData( DataFlavor.stringFlavor );
       addElement( s );
       event.getDropTargetContext().dropComplete( true );
     }
     else
     {
       event.rejectDrop();
     }
   }
   catch( Exception exception )
   {
     System.err.println( "Exception" + exception.getMessage() );
     event.rejectDrop();
   }
 }
 /**
  * is invoked if the use modifies the current drop gesture
  * 
  */
 public void dropActionChanged( DropTargetDragEvent event )
 {
 }
 /**
  * a drag gesture has been initiated
  * 
  */
 public void dragGestureRecognized( DragGestureEvent event )
 {
   Object selected = getSelectedValue();
   if( selected != null )
   {
     StringSelection text = new StringSelection( selected.toString() );
     // as the name suggests, starts the dragging
     dragSource.startDrag( event, DragSource.DefaultMoveDrop, text, this );
   }
   else
   {
     System.out.println( "nothing was selected" );
   }
 }
 /**
  * this message goes to DragSourceListener, informing it that the dragging
  * has ended
  * 
  */
 public void dragDropEnd( DragSourceDropEvent event )
 {
   if( event.getDropSuccess() )
   {
     removeElement();
   }
 }
 /**
  * this message goes to DragSourceListener, informing it that the dragging
  * has entered the DropSite
  * 
  */
 public void dragEnter( DragSourceDragEvent event )
 {
   System.out.println( " dragEnter" );
 }
 /**
  * this message goes to DragSourceListener, informing it that the dragging
  * has exited the DropSite
  * 
  */
 public void dragExit( DragSourceEvent event )
 {
   System.out.println( "dragExit" );
 }
 /**
  * this message goes to DragSourceListener, informing it that the dragging is
  * currently ocurring over the DropSite
  * 
  */
 public void dragOver( DragSourceDragEvent event )
 {
   System.out.println( "dragExit" );
 }
 /**
  * is invoked when the user changes the dropAction
  * 
  */
 public void dropActionChanged( DragSourceDragEvent event )
 {
   System.out.println( "dropActionChanged" );
 }
 /**
  * adds elements to itself
  * 
  */
 public void addElement( Object s )
 {
   ( ( DefaultListModel )getModel() ).addElement( s.toString() );
 }
 /**
  * removes an element from itself
  */
 public void removeElement()
 {
   ( ( DefaultListModel )getModel() ).removeElement( getSelectedValue() );
 }

}</source>





14. Drag and drop between JList and JTextField

   <source lang="java">

import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DnDDemo3 {

 public static void main(String[] args) {
   JPanel north = new JPanel();
   north.add(new JLabel("Drag from here:"));
   JTextField field = new JTextField(10);
   field.setDragEnabled(true); 
   north.add(field);
   final DefaultListModel listModel = new DefaultListModel();
   listModel.addElement("first");
   listModel.addElement("second");
   final JList list = new JList(listModel);
   list.setDragEnabled(true);
   list.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       if (dl.getIndex() == -1) {
         return false;
       } else {
         return true;
       }
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       Transferable transferable = support.getTransferable();
       String data;
       try {
         data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (Exception e) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       int index = dl.getIndex();
       if (dl.isInsert()) {
         listModel.add(index, data);
       } else {
         listModel.set(index, data);
       }
       Rectangle r = list.getCellBounds(index, index);
       list.scrollRectToVisible(r);
       return true;
     }
   });
   JScrollPane center = new JScrollPane();
   center.setViewportView(list);
   list.setDropMode(DropMode.USE_SELECTION);
   JPanel cp = new JPanel();
   cp.setLayout(new BorderLayout());
   cp.add(north, BorderLayout.NORTH);
   cp.add(center, BorderLayout.CENTER);
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(cp);
   frame.pack();
   frame.setVisible(true);
 }

}</source>





14. Drag and drop between JTextArea and JTextField

   <source lang="java">

import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; public class DnDBetweenJTextAreaAndJTextFieldDemo {

 public static void main(String[] args) {
   JFrame frame = new JFrame("Drag and Drop Demo");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(new JPanel());
   JTextField textField = new JTextField(25);
   textField.setText("www.jexp.ru");
   frame.add(textField);
   JTextArea textArea = new JTextArea(4, 25);
   textArea.setText("Demonstrating\ndrag and drop");
   frame.getContentPane().add(new JScrollPane(textArea));
   textArea.setDragEnabled(true);
   textField.setDragEnabled(true);
   frame.pack();
   frame.setVisible(true);
 }

}</source>





14. Drag-and-Drop customization: drag the foreground color from the first label and drop it as the background color into the second one

   <source lang="java">

/*

* Copyright (c) 2004 David Flanagan.  All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book, 
* please visit http://www.davidflanagan.ru/javaexamples3.
*/

import java.awt.Color; import java.awt.FlowLayout; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.TransferHandler; /**

* Simple Drag-and-Drop customization: drag the foreground color from the first
* label and drop it as the background color into the second one. Try it also
* using the ShowBean program to display a JColorChooser component with
* dragEnabled=true.
*/

public class ColorDrag {

 public static void main(String args[]) {
   // Create two JLabel objects
   final JLabel label1 = new JLabel("Drag here");
   JLabel label2 = new JLabel("Drop here");
   // Register TransferHandler objects on them: label1 transfers its
   // foreground color and label2 transfers its background color.
   label1.setTransferHandler(new TransferHandler("foreground"));
   label2.setTransferHandler(new TransferHandler("background"));
   // Give label1 a foreground color other than the default
   // Make label2 opaque so it displays its background color
   label1.setForeground(new Color(100, 100, 200));
   label2.setOpaque(true);
   // Now look for drag gestures over label1. When one occurs,
   // tell the TransferHandler to begin a drag.
   // Exercise: modify this gesture recognition so that the drag doesn"t
   // begin until the mouse has moved 4 pixels. This helps to keep
   // drags distinct from sloppy clicks. To do this, you"ll need both
   // a MouseListener and a MouseMotionListener.
   label1.addMouseMotionListener(new MouseMotionAdapter() {
     public void mouseDragged(MouseEvent e) {
       TransferHandler handler = label1.getTransferHandler();
       handler.exportAsDrag(label1, e, TransferHandler.COPY);
     }
   });
   // Create a window, add the labels, and make it all visible.
   JFrame f = new JFrame("ColorDrag");
   f.getContentPane().setLayout(new FlowLayout());
   f.getContentPane().add(label1);
   f.getContentPane().add(label2);
   f.pack();
   f.setVisible(true);
 }

}</source>





14. Drag and drop icons: use an icon property.

   <source lang="java">

import java.awt.FlowLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.TransferHandler; class DragMouseAdapter extends MouseAdapter {

 public void mousePressed(MouseEvent e) {
   JComponent c = (JComponent) e.getSource();
   TransferHandler handler = c.getTransferHandler();
   handler.exportAsDrag(c, e, TransferHandler.COPY);
 }

} public class IconDnD {

 public static void main(String[] args) {
   JFrame f = new JFrame("Icon Drag & Drop");
   ImageIcon icon1 = new ImageIcon("a.png");
   ImageIcon icon2 = new ImageIcon("b.png");
   ImageIcon icon3 = new ImageIcon("c.png");
   JButton button = new JButton(icon2);
   JLabel label1 = new JLabel(icon1, JLabel.CENTER);
   JLabel label2 = new JLabel(icon3, JLabel.CENTER);
   MouseListener listener = new DragMouseAdapter();
   label1.addMouseListener(listener);
   label2.addMouseListener(listener);
   label1.setTransferHandler(new TransferHandler("icon"));
   button.setTransferHandler(new TransferHandler("icon"));
   label2.setTransferHandler(new TransferHandler("icon"));
   f.setLayout(new FlowLayout());
   f.add(label1);
   f.add(button);
   f.add(label2);
   f.pack();
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   f.setVisible(true);
 }

}</source>





14. Drag-and-Drop Support for Images

To transfer something other than a simple property, you need to create an implementation of the Transferable interface,



   <source lang="java">

import java.awt.BorderLayout; import java.awt.Image; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.IOException; import javax.swing.AbstractButton; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.TransferHandler; class ImageSelection extends TransferHandler implements Transferable {

 private static final DataFlavor flavors[] = { DataFlavor.imageFlavor };
 private Image image;
 public int getSourceActions(JComponent c) {
   return TransferHandler.COPY;
 }
 public boolean canImport(JComponent comp, DataFlavor flavor[]) {
   if (!(comp instanceof JLabel) && !(comp instanceof AbstractButton)) {
     return false;
   }
   for (int i = 0, n = flavor.length; i < n; i++) {
     for (int j = 0, m = flavors.length; j < m; j++) {
       if (flavor[i].equals(flavors[j])) {
         return true;
       }
     }
   }
   return false;
 }
 public Transferable createTransferable(JComponent comp) {
   // Clear
   image = null;
   if (comp instanceof JLabel) {
     JLabel label = (JLabel) comp;
     Icon icon = label.getIcon();
     if (icon instanceof ImageIcon) {
       image = ((ImageIcon) icon).getImage();
       return this;
     }
   } else if (comp instanceof AbstractButton) {
     AbstractButton button = (AbstractButton) comp;
     Icon icon = button.getIcon();
     if (icon instanceof ImageIcon) {
       image = ((ImageIcon) icon).getImage();
       return this;
     }
   }
   return null;
 }
 public boolean importData(JComponent comp, Transferable t) {
   if (comp instanceof JLabel) {
     JLabel label = (JLabel) comp;
     if (t.isDataFlavorSupported(flavors[0])) {
       try {
         image = (Image) t.getTransferData(flavors[0]);
         ImageIcon icon = new ImageIcon(image);
         label.setIcon(icon);
         return true;
       } catch (UnsupportedFlavorException ignored) {
       } catch (IOException ignored) {
       }
     }
   } else if (comp instanceof AbstractButton) {
     AbstractButton button = (AbstractButton) comp;
     if (t.isDataFlavorSupported(flavors[0])) {
       try {
         image = (Image) t.getTransferData(flavors[0]);
         ImageIcon icon = new ImageIcon(image);
         button.setIcon(icon);
         return true;
       } catch (UnsupportedFlavorException ignored) {
       } catch (IOException ignored) {
       }
     }
   }
   return false;
 }
 // Transferable
 public Object getTransferData(DataFlavor flavor) {
   if (isDataFlavorSupported(flavor)) {
     return image;
   }
   return null;
 }
 public DataFlavor[] getTransferDataFlavors() {
   return flavors;
 }
 public boolean isDataFlavorSupported(DataFlavor flavor) {
   return flavors[0].equals(flavor);
 }

} public class DragImage {

 public static void main(String args[]) {
   JFrame frame = new JFrame("Drag Image");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   Icon icon = new ImageIcon("yourFile.gif");
   JLabel label = new JLabel(icon);
   label.setTransferHandler(new ImageSelection());
   MouseListener listener = new MouseAdapter() {
     public void mousePressed(MouseEvent me) {
       JComponent comp = (JComponent) me.getSource();
       TransferHandler handler = comp.getTransferHandler();
       handler.exportAsDrag(comp, me, TransferHandler.COPY);
     }
   };
   label.addMouseListener(listener);
   frame.add(new JScrollPane(label), BorderLayout.CENTER);
   frame.setSize(300, 150);
   frame.setVisible(true);
 }

}</source>





14. Dragging and dropping text between a text area, a list, and a table

   <source lang="java">

/*

*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.ListSelectionModel; import javax.swing.TransferHandler; import javax.swing.table.DefaultTableModel; public class ExtendedDnDDemo extends JPanel {

   public ExtendedDnDDemo() {
       super(new GridLayout(3,1));
       add(createArea());
       add(createList());
       add(createTable());
   }
   
   private JPanel createList() {
       DefaultListModel listModel = new DefaultListModel();
       listModel.addElement("List 0");
       listModel.addElement("List 1");
       listModel.addElement("List 2");
       listModel.addElement("List 3");
       listModel.addElement("List 4");
       listModel.addElement("List 5");
       listModel.addElement("List 6");
       listModel.addElement("List 7");
       listModel.addElement("List 8");
       
       JList list = new JList(listModel);
       list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
       JScrollPane scrollPane = new JScrollPane(list);
       scrollPane.setPreferredSize(new Dimension(400,100));
       
       list.setDragEnabled(true);
       list.setTransferHandler(new ListTransferHandler());
       
       JPanel panel = new JPanel(new BorderLayout());
       panel.add(scrollPane, BorderLayout.CENTER);
       panel.setBorder(BorderFactory.createTitledBorder("List"));
       return panel;
   }
   
   private JPanel createArea() {
       String text = "This is the text that I want to show.";
       
       JTextArea area = new JTextArea();
       area.setText(text);
       area.setDragEnabled(true);
       JScrollPane scrollPane = new JScrollPane(area);
       scrollPane.setPreferredSize(new Dimension(400,100));
       JPanel panel = new JPanel(new BorderLayout());
       panel.add(scrollPane, BorderLayout.CENTER);
       panel.setBorder(BorderFactory.createTitledBorder("Text Area"));
       return panel;
   }
   private JPanel createTable() {
       DefaultTableModel model = new DefaultTableModel();
       
       model.addColumn("Column 0");
       model.addColumn("Column 1");
       model.addColumn("Column 2");
       model.addColumn("Column 3");
       
       model.addRow(new String[]{"Table 00", "Table 01",
                                 "Table 02", "Table 03"});
       model.addRow(new String[]{"Table 10", "Table 11",
                                 "Table 12", "Table 13"});
       model.addRow(new String[]{"Table 20", "Table 21",
                                 "Table 22", "Table 23"});
       model.addRow(new String[]{"Table 30", "Table 31",
                                 "Table 32", "Table 33"});
       JTable table = new JTable(model);
       table.getTableHeader().setReorderingAllowed(false);
       table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
       JScrollPane scrollPane = new JScrollPane(table);
       scrollPane.setPreferredSize(new Dimension(400,100));
       table.setDragEnabled(true);
       table.setTransferHandler(new TableTransferHandler());
       JPanel panel = new JPanel(new BorderLayout());
       panel.add(scrollPane, BorderLayout.CENTER);
       panel.setBorder(BorderFactory.createTitledBorder("Table"));
       return panel;
   }
   /**
    * Create the GUI and show it.  For thread safety,
    * this method should be invoked from the
    * event-dispatching thread.
    */
   private static void createAndShowGUI() {
       //Create and set up the window.
       JFrame frame = new JFrame("ExtendedDnDDemo");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       //Create and set up the content pane.
       JComponent newContentPane = new ExtendedDnDDemo();
       newContentPane.setOpaque(true); //content panes must be opaque
       frame.setContentPane(newContentPane);
       //Display the window.
       frame.pack();
       frame.setVisible(true);
   }
   public static void main(String[] args) {
       //Schedule a job for the event-dispatching thread:
       //creating and showing this application"s GUI.
       javax.swing.SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               createAndShowGUI();
           }
       });
   }

} abstract class StringTransferHandler extends TransferHandler {

   protected abstract String exportString(JComponent c);
   protected abstract void importString(JComponent c, String str);
   protected abstract void cleanup(JComponent c, boolean remove);
   
   protected Transferable createTransferable(JComponent c) {
       return new StringSelection(exportString(c));
   }
   
   public int getSourceActions(JComponent c) {
       return COPY_OR_MOVE;
   }
   
   public boolean importData(JComponent c, Transferable t) {
       if (canImport(c, t.getTransferDataFlavors())) {
           try {
               String str = (String)t.getTransferData(DataFlavor.stringFlavor);
               importString(c, str);
               return true;
           } catch (UnsupportedFlavorException ufe) {
           } catch (IOException ioe) {
           }
       }
       return false;
   }
   
   protected void exportDone(JComponent c, Transferable data, int action) {
       cleanup(c, action == MOVE);
   }
   
   public boolean canImport(JComponent c, DataFlavor[] flavors) {
       for (int i = 0; i < flavors.length; i++) {
           if (DataFlavor.stringFlavor.equals(flavors[i])) {
               return true;
           }
       }
       return false;
   }

} class ListTransferHandler extends StringTransferHandler {

   private int[] indices = null;
   private int addIndex = -1; //Location where items were added
   private int addCount = 0;  //Number of items added.
           
   //Bundle up the selected items in the list
   //as a single string, for export.
   protected String exportString(JComponent c) {
       JList list = (JList)c;
       indices = list.getSelectedIndices();
       Object[] values = list.getSelectedValues();
       
       StringBuffer buff = new StringBuffer();
       for (int i = 0; i < values.length; i++) {
           Object val = values[i];
           buff.append(val == null ? "" : val.toString());
           if (i != values.length - 1) {
               buff.append("\n");
           }
       }
       
       return buff.toString();
   }
   //Take the incoming string and wherever there is a
   //newline, break it into a separate item in the list.
   protected void importString(JComponent c, String str) {
       JList target = (JList)c;
       DefaultListModel listModel = (DefaultListModel)target.getModel();
       int index = target.getSelectedIndex();
       //Prevent the user from dropping data back on itself.
       //For example, if the user is moving items #4,#5,#6 and #7 and
       //attempts to insert the items after item #5, this would
       //be problematic when removing the original items.
       //So this is not allowed.
       if (indices != null && index >= indices[0] - 1 &&
             index <= indices[indices.length - 1]) {
           indices = null;
           return;
       }
       int max = listModel.getSize();
       if (index < 0) {
           index = max;
       } else {
           index++;
           if (index > max) {
               index = max;
           }
       }
       addIndex = index;
       String[] values = str.split("\n");
       addCount = values.length;
       for (int i = 0; i < values.length; i++) {
           listModel.add(index++, values[i]);
       }
   }
   //If the remove argument is true, the drop has been
   //successful and it"s time to remove the selected items 
   //from the list. If the remove argument is false, it
   //was a Copy operation and the original list is left
   //intact.
   protected void cleanup(JComponent c, boolean remove) {
       if (remove && indices != null) {
           JList source = (JList)c;
           DefaultListModel model  = (DefaultListModel)source.getModel();
           //If we are moving items around in the same list, we
           //need to adjust the indices accordingly, since those
           //after the insertion point have moved.
           if (addCount > 0) {
               for (int i = 0; i < indices.length; i++) {
                   if (indices[i] > addIndex) {
                       indices[i] += addCount;
                   }
               }
           }
           for (int i = indices.length - 1; i >= 0; i--) {
               model.remove(indices[i]);
           }
       }
       indices = null;
       addCount = 0;
       addIndex = -1;
   }

} class TableTransferHandler extends StringTransferHandler {

   private int[] rows = null;
   private int addIndex = -1; //Location where items were added
   private int addCount = 0;  //Number of items added.
   protected String exportString(JComponent c) {
       JTable table = (JTable)c;
       rows = table.getSelectedRows();
       int colCount = table.getColumnCount();
       
       StringBuffer buff = new StringBuffer();
       
       for (int i = 0; i < rows.length; i++) {
           for (int j = 0; j < colCount; j++) {
               Object val = table.getValueAt(rows[i], j);
               buff.append(val == null ? "" : val.toString());
               if (j != colCount - 1) {
                   buff.append(",");
               }
           }
           if (i != rows.length - 1) {
               buff.append("\n");
           }
       }
       
       return buff.toString();
   }
   protected void importString(JComponent c, String str) {
       JTable target = (JTable)c;
       DefaultTableModel model = (DefaultTableModel)target.getModel();
       int index = target.getSelectedRow();
       //Prevent the user from dropping data back on itself.
       //For example, if the user is moving rows #4,#5,#6 and #7 and
       //attempts to insert the rows after row #5, this would
       //be problematic when removing the original rows.
       //So this is not allowed.
       if (rows != null && index >= rows[0] - 1 &&
             index <= rows[rows.length - 1]) {
           rows = null;
           return;
       }
       int max = model.getRowCount();
       if (index < 0) {
           index = max;
       } else {
           index++;
           if (index > max) {
               index = max;
           }
       }
       addIndex = index;
       String[] values = str.split("\n");
       addCount = values.length;
       int colCount = target.getColumnCount();
       for (int i = 0; i < values.length && i < colCount; i++) {
           model.insertRow(index++, values[i].split(","));
       }
   }
   protected void cleanup(JComponent c, boolean remove) {
       JTable source = (JTable)c;
       if (remove && rows != null) {
           DefaultTableModel model =
                (DefaultTableModel)source.getModel();
           //If we are moving items around in the same table, we
           //need to adjust the rows accordingly, since those
           //after the insertion point have moved.
           if (addCount > 0) {
               for (int i = 0; i < rows.length; i++) {
                   if (rows[i] > addIndex) {
                       rows[i] += addCount;
                   }
               }
           }
           for (int i = rows.length - 1; i >= 0; i--) {
               model.removeRow(rows[i]);
           }
       }
       rows = null;
       addCount = 0;
       addIndex = -1;
   }

}</source>





14. Dragging Text from a JLabel

   <source lang="java">

import java.awt.BorderLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DragLabel {

 public static void main(String args[]) {
   JFrame frame = new JFrame("Drag Label");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   JLabel label = new JLabel("Hello, World");
   label.setTransferHandler(new TransferHandler("foreground"));
   MouseListener listener = new MouseAdapter() {
     public void mousePressed(MouseEvent me) {
       JComponent comp = (JComponent) me.getSource();
       TransferHandler handler = comp.getTransferHandler();
       handler.exportAsDrag(comp, me, TransferHandler.COPY);
     }
   };
   label.addMouseListener(listener);
   frame.add(label, BorderLayout.SOUTH);
   JTextField text = new JTextField();
   frame.add(text, BorderLayout.NORTH);
   frame.setSize(300, 150);
   frame.setVisible(true);
 }

}</source>





14. DropMode.INSERT

   <source lang="java">

import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DropModeINSERT {

 public static void main(String[] args) {
   JPanel north = new JPanel();
   north.add(new JLabel("Drag from here:"));
   JTextField field = new JTextField(10);
   field.setDragEnabled(true); 
   north.add(field);
   final DefaultListModel listModel = new DefaultListModel();
   listModel.addElement("first");
   listModel.addElement("second");
   final JList list = new JList(listModel);
   list.setDragEnabled(true);
   list.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       if (dl.getIndex() == -1) {
         return false;
       } else {
         return true;
       }
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       Transferable transferable = support.getTransferable();
       String data;
       try {
         data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (Exception e) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       int index = dl.getIndex();
       if (dl.isInsert()) {
         listModel.add(index, data);
       } else {
         listModel.set(index, data);
       }
       // Scroll to display the element that was dropped
       Rectangle r = list.getCellBounds(index, index);
       list.scrollRectToVisible(r);
       return true;
     }
   });
   JScrollPane center = new JScrollPane();
   center.setViewportView(list);
   list.setDropMode(DropMode.INSERT);
   JPanel cp = new JPanel();
   cp.setLayout(new BorderLayout());
   cp.add(north, BorderLayout.NORTH);
   cp.add(center, BorderLayout.CENTER);
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(cp);
   frame.pack();
   frame.setVisible(true);
 }

}</source>





14. DropMode.ON

   <source lang="java">

import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DropModeON {

 public static void main(String[] args) {
   JPanel north = new JPanel();
   north.add(new JLabel("Drag from here:"));
   JTextField field = new JTextField(10);
   field.setDragEnabled(true); 
   north.add(field);
   final DefaultListModel listModel = new DefaultListModel();
   listModel.addElement("first");
   listModel.addElement("second");
   final JList list = new JList(listModel);
   list.setDragEnabled(true);
   list.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       if (dl.getIndex() == -1) {
         return false;
       } else {
         return true;
       }
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       Transferable transferable = support.getTransferable();
       String data;
       try {
         data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (Exception e) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       int index = dl.getIndex();
       if (dl.isInsert()) {
         listModel.add(index, data);
       } else {
         listModel.set(index, data);
       }
       // Scroll to display the element that was dropped
       Rectangle r = list.getCellBounds(index, index);
       list.scrollRectToVisible(r);
       return true;
     }
   });
   JScrollPane center = new JScrollPane();
   center.setViewportView(list);
   list.setDropMode(DropMode.ON);
   JPanel cp = new JPanel();
   cp.setLayout(new BorderLayout());
   cp.add(north, BorderLayout.NORTH);
   cp.add(center, BorderLayout.CENTER);
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(cp);
   frame.pack();
   frame.setVisible(true);
 }

}</source>





14. DropMode.ON_OR_INSERT

   <source lang="java">

import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.TransferHandler; public class DropModeON_OR_INSERT {

 public static void main(String[] args) {
   JPanel north = new JPanel();
   north.add(new JLabel("Drag from here:"));
   JTextField field = new JTextField(10);
   field.setDragEnabled(true); 
   north.add(field);
   final DefaultListModel listModel = new DefaultListModel();
   listModel.addElement("first");
   listModel.addElement("second");
   final JList list = new JList(listModel);
   list.setDragEnabled(true);
   list.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       if (dl.getIndex() == -1) {
         return false;
       } else {
         return true;
       }
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       Transferable transferable = support.getTransferable();
       String data;
       try {
         data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (Exception e) {
         return false;
       }
       JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
       int index = dl.getIndex();
       if (dl.isInsert()) {
         listModel.add(index, data);
       } else {
         listModel.set(index, data);
       }
       // Scroll to display the element that was dropped
       Rectangle r = list.getCellBounds(index, index);
       list.scrollRectToVisible(r);
       return true;
     }
   });
   JScrollPane center = new JScrollPane();
   center.setViewportView(list);
   list.setDropMode(DropMode.ON_OR_INSERT);
   JPanel cp = new JPanel();
   cp.setLayout(new BorderLayout());
   cp.add(north, BorderLayout.NORTH);
   cp.add(center, BorderLayout.CENTER);
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(cp);
   frame.pack();
   frame.setVisible(true);
 }

}</source>





14. Illustrates cut, copy, paste and drag and drop using three instances of JList

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**

* ListCutPaste.java requires the following files:
*     ListTransferHandler.java
*     TransferActionListener.java
*/

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.KeyboardFocusManager; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.TransferHandler; import javax.swing.UIManager; /**

* The ListCutPaste example illustrates cut, copy, paste and drag and drop using
* three instances of JList. The TransferActionListener class listens for one of
* the CCP actions and, when one occurs, forwards the action to the component
* which currently has the focus.
*/

public class ListCutPaste extends JPanel {

 ListTransferHandler lh;
 public ListCutPaste() {
   super(new BorderLayout());
   lh = new ListTransferHandler();
   JPanel panel = new JPanel(new GridLayout(1, 3));
   DefaultListModel list1Model = new DefaultListModel();
   list1Model.addElement("alpha");
   list1Model.addElement("beta");
   list1Model.addElement("gamma");
   list1Model.addElement("delta");
   list1Model.addElement("epsilon");
   list1Model.addElement("zeta");
   JList list1 = new JList(list1Model);
   list1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
   JScrollPane sp1 = new JScrollPane(list1);
   sp1.setPreferredSize(new Dimension(400, 100));
   list1.setDragEnabled(true);
   list1.setTransferHandler(lh);
   list1.setDropMode(DropMode.ON_OR_INSERT);
   setMappings(list1);
   JPanel pan1 = new JPanel(new BorderLayout());
   pan1.add(sp1, BorderLayout.CENTER);
   pan1.setBorder(BorderFactory.createTitledBorder("Greek Alphabet"));
   panel.add(pan1);
   DefaultListModel list2Model = new DefaultListModel();
   list2Model.addElement("uma");
   list2Model.addElement("dois");
   list2Model.addElement("tres");
   list2Model.addElement("quatro");
   list2Model.addElement("cinco");
   list2Model.addElement("seis");
   JList list2 = new JList(list2Model);
   list2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
   list2.setDragEnabled(true);
   JScrollPane sp2 = new JScrollPane(list2);
   sp2.setPreferredSize(new Dimension(400, 100));
   list2.setTransferHandler(lh);
   list2.setDropMode(DropMode.INSERT);
   setMappings(list2);
   JPanel pan2 = new JPanel(new BorderLayout());
   pan2.add(sp2, BorderLayout.CENTER);
   pan2.setBorder(BorderFactory.createTitledBorder("Portuguese Numbers"));
   panel.add(pan2);
   DefaultListModel list3Model = new DefaultListModel();
   list3Model.addElement("adeen");
   list3Model.addElement("dva");
   list3Model.addElement("tri");
   list3Model.addElement("chyetirye");
   list3Model.addElement("pyat");
   list3Model.addElement("shest");
   JList list3 = new JList(list3Model);
   list3.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
   list3.setDragEnabled(true);
   JScrollPane sp3 = new JScrollPane(list3);
   sp3.setPreferredSize(new Dimension(400, 100));
   list3.setTransferHandler(lh);
   list3.setDropMode(DropMode.ON);
   setMappings(list3);
   JPanel pan3 = new JPanel(new BorderLayout());
   pan3.add(sp3, BorderLayout.CENTER);
   pan3.setBorder(BorderFactory.createTitledBorder("Russian Numbers"));
   panel.add(pan3);
   setPreferredSize(new Dimension(500, 200));
   add(panel, BorderLayout.CENTER);
 }
 /**
  * Create an Edit menu to support cut/copy/paste.
  */
 public JMenuBar createMenuBar() {
   JMenuItem menuItem = null;
   JMenuBar menuBar = new JMenuBar();
   JMenu mainMenu = new JMenu("Edit");
   mainMenu.setMnemonic(KeyEvent.VK_E);
   TransferActionListener actionListener = new TransferActionListener();
   menuItem = new JMenuItem("Cut");
   menuItem.setActionCommand((String) TransferHandler.getCutAction().getValue(
       Action.NAME));
   menuItem.addActionListener(actionListener);
   menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
       ActionEvent.CTRL_MASK));
   menuItem.setMnemonic(KeyEvent.VK_T);
   mainMenu.add(menuItem);
   menuItem = new JMenuItem("Copy");
   menuItem.setActionCommand((String) TransferHandler.getCopyAction()
       .getValue(Action.NAME));
   menuItem.addActionListener(actionListener);
   menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
       ActionEvent.CTRL_MASK));
   menuItem.setMnemonic(KeyEvent.VK_C);
   mainMenu.add(menuItem);
   menuItem = new JMenuItem("Paste");
   menuItem.setActionCommand((String) TransferHandler.getPasteAction()
       .getValue(Action.NAME));
   menuItem.addActionListener(actionListener);
   menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,
       ActionEvent.CTRL_MASK));
   menuItem.setMnemonic(KeyEvent.VK_P);
   mainMenu.add(menuItem);
   menuBar.add(mainMenu);
   return menuBar;
 }
 /**
  * Add the cut/copy/paste actions to the action map.
  */
 private void setMappings(JList list) {
   ActionMap map = list.getActionMap();
   map.put(TransferHandler.getCutAction().getValue(Action.NAME),
       TransferHandler.getCutAction());
   map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
       TransferHandler.getCopyAction());
   map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
       TransferHandler.getPasteAction());
 }
 /**
  * Create the GUI and show it. For thread safety, this method should be
  * invoked from the event-dispatching thread.
  */
 private static void createAndShowGUI() {
   // Create and set up the window.
   JFrame frame = new JFrame("ListCutPaste");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   // Create and set up the menu bar and content pane.
   ListCutPaste demo = new ListCutPaste();
   frame.setJMenuBar(demo.createMenuBar());
   demo.setOpaque(true); // content panes must be opaque
   frame.setContentPane(demo);
   // Display the window.
   frame.pack();
   frame.setVisible(true);
 }
 public static void main(String[] args) {
   // Schedule a job for the event-dispatching thread:
   // creating and showing this application"s GUI.
   javax.swing.SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       // Turn off metal"s use of bold fonts
       UIManager.put("swing.boldMetal", Boolean.FALSE);
       createAndShowGUI();
     }
   });
 }

}/*

  * Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved.
  * 
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *  - Redistributions of source code must retain the above copyright notice,
  * this list of conditions and the following disclaimer.
  *  - Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
  *  - Neither the name of Sun Microsystems nor the names of its contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
  * 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */

/*

* ListTransferHandler.java is used by the ListCutPaste example.
*/

class ListTransferHandler extends TransferHandler {

 /**
  * Perform the actual data import.
  */
 public boolean importData(TransferHandler.TransferSupport info) {
   String data = null;
   // If we can"t handle the import, bail now.
   if (!canImport(info)) {
     return false;
   }
   JList list = (JList) info.getComponent();
   DefaultListModel model = (DefaultListModel) list.getModel();
   // Fetch the data -- bail if this fails
   try {
     data = (String) info.getTransferable().getTransferData(
         DataFlavor.stringFlavor);
   } catch (UnsupportedFlavorException ufe) {
     System.out.println("importData: unsupported data flavor");
     return false;
   } catch (IOException ioe) {
     System.out.println("importData: I/O exception");
     return false;
   }
   if (info.isDrop()) { // This is a drop
     JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
     int index = dl.getIndex();
     if (dl.isInsert()) {
       model.add(index, data);
       return true;
     } else {
       model.set(index, data);
       return true;
     }
   } else { // This is a paste
     int index = list.getSelectedIndex();
     // if there is a valid selection,
     // insert data after the selection
     if (index >= 0) {
       model.add(list.getSelectedIndex() + 1, data);
       // else append to the end of the list
     } else {
       model.addElement(data);
     }
     return true;
   }
 }
 /**
  * Bundle up the data for export.
  */
 protected Transferable createTransferable(JComponent c) {
   JList list = (JList) c;
   int index = list.getSelectedIndex();
   String value = (String) list.getSelectedValue();
   return new StringSelection(value);
 }
 /**
  * The list handles both copy and move actions.
  */
 public int getSourceActions(JComponent c) {
   return COPY_OR_MOVE;
 }
 /**
  * When the export is complete, remove the old list entry if the action was a
  * move.
  */
 protected void exportDone(JComponent c, Transferable data, int action) {
   if (action != MOVE) {
     return;
   }
   JList list = (JList) c;
   DefaultListModel model = (DefaultListModel) list.getModel();
   int index = list.getSelectedIndex();
   model.remove(index);
 }
 /**
  * We only support importing strings.
  */
 public boolean canImport(TransferHandler.TransferSupport support) {
   // we only import Strings
   if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
     return false;
   }
   return true;
 }

} /*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved.
* 
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*  - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*  - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*  - Neither the name of Sun Microsystems nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/*

* TransferActionListener.java is used by the ListCutPaste example.
*/

/**

* A class that tracks the focused component. This is necessary to delegate the
* menu cut/copy/paste commands to the right component. An instance of this
* class is listening and when the user fires one of these commands, it calls
* the appropriate action on the currently focused component.
*/

class TransferActionListener implements ActionListener, PropertyChangeListener {

 private JComponent focusOwner = null;
 public TransferActionListener() {
   KeyboardFocusManager manager = KeyboardFocusManager
       .getCurrentKeyboardFocusManager();
   manager.addPropertyChangeListener("permanentFocusOwner", this);
 }
 public void propertyChange(PropertyChangeEvent e) {
   Object o = e.getNewValue();
   if (o instanceof JComponent) {
     focusOwner = (JComponent) o;
   } else {
     focusOwner = null;
   }
 }
 public void actionPerformed(ActionEvent e) {
   if (focusOwner == null)
     return;
   String action = (String) e.getActionCommand();
   Action a = focusOwner.getActionMap().get(action);
   if (a != null) {
     a.actionPerformed(new ActionEvent(focusOwner,
         ActionEvent.ACTION_PERFORMED, null));
   }
 }

}</source>





14. implements DragGestureListener, Transferable

   <source lang="java">

import java.awt.Cursor; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import javax.swing.JFrame; import javax.swing.JLabel; public class DragGesture extends JFrame implements DragGestureListener, Transferable {

 public DragGesture() {
   setTitle("Drag Gesture");
   JLabel left = new JLabel("text");
   DragSource ds = new DragSource();
   ds.createDefaultDragGestureRecognizer(left, DnDConstants.ACTION_COPY, this);
   add(left);
   pack();
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   setVisible(true);
 }
 public void dragGestureRecognized(DragGestureEvent event) {
   Cursor cursor = null;
   if (event.getDragAction() == DnDConstants.ACTION_COPY) {
     cursor = DragSource.DefaultCopyDrop;
   }
   event.startDrag(cursor, this);
 }
 public Object getTransferData(DataFlavor flavor) {
   return null;
 }
 public DataFlavor[] getTransferDataFlavors() {
   return new DataFlavor[0];
 }
 public boolean isDataFlavorSupported(DataFlavor flavor) {
   return false;
 }
 public static void main(String[] args) {
   new DragGesture();
 }

}</source>





14. JTable drag and drop

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; public class FillViewportHeightDemo extends JFrame implements ActionListener {

 private DefaultListModel model = new DefaultListModel();
 private int count = 0;
 private JTable table;
 private JCheckBoxMenuItem fillBox;
 private DefaultTableModel tableModel;
 private static String getNextString(int count) {
   StringBuffer buf = new StringBuffer();
   for (int i = 0; i < 5; i++) {
     buf.append(String.valueOf(count));
     buf.append(",");
   }
   // remove last newline
   buf.deleteCharAt(buf.length() - 1);
   return buf.toString();
 }
 private static DefaultTableModel getDefaultTableModel() {
   String[] cols = { "Foo", "Toto", "Kala", "Pippo", "Boing" };
   return new DefaultTableModel(null, cols);
 }
 public FillViewportHeightDemo() {
   super("Empty Table DnD Demo");
   tableModel = getDefaultTableModel();
   table = new JTable(tableModel);
   table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
   table.setDropMode(DropMode.INSERT_ROWS);
   table.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferSupport support) {
       // for the demo, we"ll only support drops (not clipboard paste)
       if (!support.isDrop()) {
         return false;
       }
       // we only import Strings
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       return true;
     }
     public boolean importData(TransferSupport support) {
       // if we can"t handle the import, say so
       if (!canImport(support)) {
         return false;
       }
       // fetch the drop location
       JTable.DropLocation dl = (JTable.DropLocation) support
           .getDropLocation();
       int row = dl.getRow();
       // fetch the data and bail if this fails
       String data;
       try {
         data = (String) support.getTransferable().getTransferData(
             DataFlavor.stringFlavor);
       } catch (UnsupportedFlavorException e) {
         return false;
       } catch (IOException e) {
         return false;
       }
       String[] rowData = data.split(",");
       tableModel.insertRow(row, rowData);
       Rectangle rect = table.getCellRect(row, 0, false);
       if (rect != null) {
         table.scrollRectToVisible(rect);
       }
       // demo stuff - remove for blog
       model.removeAllElements();
       model.insertElementAt(getNextString(count++), 0);
       // end demo stuff
       return true;
     }
   });
   JList dragFrom = new JList(model);
   dragFrom.setFocusable(false);
   dragFrom.setPrototypeCellValue(getNextString(100));
   model.insertElementAt(getNextString(count++), 0);
   dragFrom.setDragEnabled(true);
   dragFrom.setBorder(BorderFactory.createLoweredBevelBorder());
   dragFrom.addMouseListener(new MouseAdapter() {
     public void mouseClicked(MouseEvent me) {
       if (SwingUtilities.isLeftMouseButton(me) && me.getClickCount() % 2 == 0) {
         String text = (String) model.getElementAt(0);
         String[] rowData = text.split(",");
         tableModel.insertRow(table.getRowCount(), rowData);
         model.removeAllElements();
         model.insertElementAt(getNextString(count++), 0);
       }
     }
   });
   JPanel p = new JPanel();
   p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
   JPanel wrap = new JPanel();
   wrap.add(new JLabel("Drag from here:"));
   wrap.add(dragFrom);
   p.add(Box.createHorizontalStrut(4));
   p.add(Box.createGlue());
   p.add(wrap);
   p.add(Box.createGlue());
   p.add(Box.createHorizontalStrut(4));
   getContentPane().add(p, BorderLayout.NORTH);
   JScrollPane sp = new JScrollPane(table);
   getContentPane().add(sp, BorderLayout.CENTER);
   fillBox = new JCheckBoxMenuItem("Fill Viewport Height");
   fillBox.addActionListener(this);
   JMenuBar mb = new JMenuBar();
   JMenu options = new JMenu("Options");
   mb.add(options);
   setJMenuBar(mb);
   JMenuItem clear = new JMenuItem("Reset");
   clear.addActionListener(this);
   options.add(clear);
   options.add(fillBox);
   getContentPane().setPreferredSize(new Dimension(260, 180));
 }
 public void actionPerformed(ActionEvent ae) {
   if (ae.getSource() == fillBox) {
     table.setFillsViewportHeight(fillBox.isSelected());
   } else {
     tableModel.setRowCount(0);
     count = 0;
     model.removeAllElements();
     model.insertElementAt(getNextString(count++), 0);
   }
 }
 private static void createAndShowGUI() {
   // Create and set up the window.
   FillViewportHeightDemo test = new FillViewportHeightDemo();
   test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   // Display the window.
   test.pack();
   test.setVisible(true);
 }
 public static void main(String[] args) {
   SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       // Turn off metal"s use of bold fonts
       UIManager.put("swing.boldMetal", Boolean.FALSE);
       createAndShowGUI();
     }
   });
 }

}</source>





14. Location sensitive drag and drop

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; public class LocationSensitiveDemo extends JFrame {

 private DefaultListModel model = new DefaultListModel();
 private int count = 0;
 private JTree tree;
 private JComboBox indicateCombo;
 private DefaultTreeModel treeModel;
 private TreePath namesPath;
 private static DefaultTreeModel getDefaultTreeModel() {
   DefaultMutableTreeNode root = new DefaultMutableTreeNode("things");
   DefaultMutableTreeNode parent;
   DefaultMutableTreeNode nparent;
   parent = new DefaultMutableTreeNode("colors");
   root.add(parent);
   parent.add(new DefaultMutableTreeNode("red"));
   parent.add(new DefaultMutableTreeNode("yellow"));
   parent.add(new DefaultMutableTreeNode("green"));
   parent.add(new DefaultMutableTreeNode("blue"));
   parent.add(new DefaultMutableTreeNode("purple"));
   parent = new DefaultMutableTreeNode("names");
   root.add(parent);
   nparent = new DefaultMutableTreeNode("men");
   nparent.add(new DefaultMutableTreeNode("jack"));
   nparent.add(new DefaultMutableTreeNode("kieran"));
   nparent.add(new DefaultMutableTreeNode("william"));
   nparent.add(new DefaultMutableTreeNode("jose"));
   parent.add(nparent);
   nparent = new DefaultMutableTreeNode("women");
   nparent.add(new DefaultMutableTreeNode("jennifer"));
   nparent.add(new DefaultMutableTreeNode("holly"));
   nparent.add(new DefaultMutableTreeNode("danielle"));
   nparent.add(new DefaultMutableTreeNode("tara"));
   parent.add(nparent);
   parent = new DefaultMutableTreeNode("sports");
   root.add(parent);
   parent.add(new DefaultMutableTreeNode("basketball"));
   parent.add(new DefaultMutableTreeNode("soccer"));
   parent.add(new DefaultMutableTreeNode("football"));
   nparent = new DefaultMutableTreeNode("hockey");
   parent.add(nparent);
   nparent.add(new DefaultMutableTreeNode("ice hockey"));
   nparent.add(new DefaultMutableTreeNode("roller hockey"));
   nparent.add(new DefaultMutableTreeNode("floor hockey"));
   nparent.add(new DefaultMutableTreeNode("road hockey"));
   parent = new DefaultMutableTreeNode("food");
   root.add(parent);
   parent.add(new DefaultMutableTreeNode("pizza"));
   parent.add(new DefaultMutableTreeNode("wings"));
   parent.add(new DefaultMutableTreeNode("pasta"));
   nparent = new DefaultMutableTreeNode("fruit");
   parent.add(nparent);
   nparent.add(new DefaultMutableTreeNode("bananas"));
   nparent.add(new DefaultMutableTreeNode("apples"));
   nparent.add(new DefaultMutableTreeNode("grapes"));
   nparent.add(new DefaultMutableTreeNode("pears"));
   return new DefaultTreeModel(root);
 }
 public LocationSensitiveDemo() {
   super("Location Sensitive Drag and Drop Demo");
   treeModel = getDefaultTreeModel();
   tree = new JTree(treeModel);
   tree.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4));
   tree.getSelectionModel().setSelectionMode(
       TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
   tree.setDropMode(DropMode.ON);
   namesPath = tree.getPathForRow(2);
   tree.expandRow(2);
   tree.expandRow(1);
   tree.setRowHeight(0);
   tree.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport info) {
       // for the demo, we"ll only support drops (not clipboard paste)
       if (!info.isDrop()) {
         return false;
       }
       String item = (String) indicateCombo.getSelectedItem();
       if (item.equals("Always")) {
         info.setShowDropLocation(true);
       } else if (item.equals("Never")) {
         info.setShowDropLocation(false);
       }
       // we only import Strings
       if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
         return false;
       }
       // fetch the drop location
       JTree.DropLocation dl = (JTree.DropLocation) info.getDropLocation();
       TreePath path = dl.getPath();
       // we don"t support invalid paths or descendants of the names folder
       if (path == null || namesPath.isDescendant(path)) {
         return false;
       }
       return true;
     }
     public boolean importData(TransferHandler.TransferSupport info) {
       // if we can"t handle the import, say so
       if (!canImport(info)) {
         return false;
       }
       // fetch the drop location
       JTree.DropLocation dl = (JTree.DropLocation) info.getDropLocation();
       // fetch the path and child index from the drop location
       TreePath path = dl.getPath();
       int childIndex = dl.getChildIndex();
       // fetch the data and bail if this fails
       String data;
       try {
         data = (String) info.getTransferable().getTransferData(
             DataFlavor.stringFlavor);
       } catch (UnsupportedFlavorException e) {
         return false;
       } catch (IOException e) {
         return false;
       }
       // if child index is -1, the drop was on top of the path, so we"ll
       // treat it as inserting at the end of that path"s list of children
       if (childIndex == -1) {
         childIndex = tree.getModel().getChildCount(
             path.getLastPathComponent());
       }
       // create a new node to represent the data and insert it into the model
       DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(data);
       DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path
           .getLastPathComponent();
       treeModel.insertNodeInto(newNode, parentNode, childIndex);
       // make the new node visible and scroll so that it"s visible
       tree.makeVisible(path.pathByAddingChild(newNode));
       tree.scrollRectToVisible(tree.getPathBounds(path
           .pathByAddingChild(newNode)));
       // demo stuff - remove for blog
       model.removeAllElements();
       model.insertElementAt("String " + (++count), 0);
       // end demo stuff
       return true;
     }
   });
   JList dragFrom = new JList(model);
   dragFrom.setFocusable(false);
   dragFrom.setPrototypeCellValue("String 0123456789");
   model.insertElementAt("String " + count, 0);
   dragFrom.setDragEnabled(true);
   dragFrom.setBorder(BorderFactory.createLoweredBevelBorder());
   JPanel p = new JPanel();
   p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
   JPanel wrap = new JPanel();
   wrap.add(new JLabel("Drag from here:"));
   wrap.add(dragFrom);
   p.add(Box.createHorizontalStrut(4));
   p.add(Box.createGlue());
   p.add(wrap);
   p.add(Box.createGlue());
   p.add(Box.createHorizontalStrut(4));
   getContentPane().add(p, BorderLayout.NORTH);
   getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
   indicateCombo = new JComboBox(new String[] { "Default", "Always", "Never" });
   indicateCombo.setSelectedItem("INSERT");
   p = new JPanel();
   p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
   wrap = new JPanel();
   wrap.add(new JLabel("Show drop location:"));
   wrap.add(indicateCombo);
   p.add(Box.createHorizontalStrut(4));
   p.add(Box.createGlue());
   p.add(wrap);
   p.add(Box.createGlue());
   p.add(Box.createHorizontalStrut(4));
   getContentPane().add(p, BorderLayout.SOUTH);
   getContentPane().setPreferredSize(new Dimension(400, 450));
 }
 private static void increaseFont(String type) {
   Font font = UIManager.getFont(type);
   font = font.deriveFont(font.getSize() + 4f);
   UIManager.put(type, font);
 }
 private static void createAndShowGUI() {
   // Create and set up the window.
   LocationSensitiveDemo test = new LocationSensitiveDemo();
   test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   // Display the window.
   test.pack();
   test.setVisible(true);
 }
 public static void main(String[] args) {
   SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       try {
         UIManager
             .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
         increaseFont("Tree.font");
         increaseFont("Label.font");
         increaseFont("ComboBox.font");
         increaseFont("List.font");
       } catch (Exception e) {
       }
       // Turn off metal"s use of bold fonts
       UIManager.put("swing.boldMetal", Boolean.FALSE);
       createAndShowGUI();
     }
   });
 }

}</source>





14. Making a Component Draggable

   <source lang="java">

import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import javax.swing.JComponent; import javax.swing.JFrame; public class Main {

 public static void main(String[] argv) throws Exception {
   JComponent com = new DraggableComponent();
   JFrame f = new JFrame();
   f.add(com);
   f.setSize(300, 300);
   f.setVisible(true);
 }

} class DraggableComponent extends JComponent implements DragGestureListener, DragSourceListener {

 DragSource dragSource;
 public DraggableComponent() {
   dragSource = new DragSource();
   dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
 }
 public void dragGestureRecognized(DragGestureEvent evt) {
   Transferable t = new StringSelection("aString");
   dragSource.startDrag(evt, DragSource.DefaultCopyDrop, t, this);
 }
 public void dragEnter(DragSourceDragEvent evt) {
   System.out.println("enters");
 }
 public void dragOver(DragSourceDragEvent evt) {
   System.out.println("over");
 }
 public void dragExit(DragSourceEvent evt) {
   System.out.println("leaves");
 }
 public void dropActionChanged(DragSourceDragEvent evt) {
   System.out.println("changes the drag action between copy or move");
 }
 public void dragDropEnd(DragSourceDropEvent evt) {
   System.out.println("finishes or cancels the drag operation");
 }

}</source>





14. ScribblePane allows individual PolyLine lines to be selected, cut, copied, pasted, dragged, and dropped

   <source lang="java">

/*

* Copyright (c) 2004 David Flanagan.  All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book, 
* please visit http://www.davidflanagan.ru/javaexamples3.
*/

import java.awt.AWTEvent; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.Externalizable; import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.border.BevelBorder; import javax.swing.border.Border; import javax.swing.border.LineBorder; /**

* This rewrite of ScribblePane allows individual PolyLine lines to be selected,
* cut, copied, pasted, dragged, and dropped.
*/

public class TransferableScribblePane extends JComponent {

 List lines; // The PolyLines that comprise this scribble
 PolyLine currentLine; // The line currently being drawn
 PolyLine selectedLine; // The line that is current selected
 boolean canDragImage; // Can we drag an image of the line?
 // Lines are 3 pixels wide, and the selected line is drawn dashed
 static Stroke stroke = new BasicStroke(3.0f);
 static Stroke selectedStroke = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND,
     0f, new float[] { 3f, 3f, }, 0f);
 // Different borders indicate receptivity to drops
 static Border normalBorder = new LineBorder(Color.black, 3);
 static Border canDropBorder = new BevelBorder(BevelBorder.LOWERED);
 public static void main(String args[]) {
   JFrame f = new JFrame("ColorDrag");
   f.getContentPane().setLayout(new FlowLayout());
   f.getContentPane().add(new TransferableScribblePane());
   f.getContentPane().add(new TransferableScribblePane());
   f.pack();
   f.setVisible(true);
 }
 // The constructor method
 public TransferableScribblePane() {
   setPreferredSize(new Dimension(450, 200)); // We need a default size
   setBorder(normalBorder); // and a border.
   lines = new ArrayList(); // Start with an empty list of lines
   // Register interest in mouse button and mouse motion events.
   enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
   // Enable drag-and-drop by specifying a listener that will be
   // notified when a drag begins. dragGestureListener is defined later.
   DragSource dragSource = DragSource.getDefaultDragSource();
   dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE,
       dragGestureListener);
   // Enable drops on this component by registering a listener to
   // be notified when something is dragged or dropped over us.
   this.setDropTarget(new DropTarget(this, dropTargetListener));
   // Check whether the system allows us to drag an image of the line
   canDragImage = dragSource.isDragImageSupported();
 }
 /** We override this method to draw ourselves. */
 public void paintComponent(Graphics g) {
   // Let the superclass do its painting first
   super.paintComponent(g);
   // Make a copy of the Graphics context so we can modify it
   Graphics2D g2 = (Graphics2D) (g.create());
   // Our superclass doesn"t paint the background, so do this ourselves.
   g2.setColor(getBackground());
   g2.fillRect(0, 0, getWidth(), getHeight());
   // Set the line width and color to use for the foreground
   g2.setStroke(stroke);
   g2.setColor(this.getForeground());
   // Now loop through the PolyLine shapes and draw them all
   int numlines = lines.size();
   for (int i = 0; i < numlines; i++) {
     PolyLine line = (PolyLine) lines.get(i);
     if (line == selectedLine) { // If it is the selected line
       g2.setStroke(selectedStroke); // Set dash pattern
       g2.draw(line); // Draw the line
       g2.setStroke(stroke); // Revert to solid lines
     } else
       g2.draw(line); // Otherwise just draw the line
   }
 }
 /**
  * This method is called on mouse button events. It begins a new line or tries
  * to select an existing line.
  */
 public void processMouseEvent(MouseEvent e) {
   if (e.getButton() == MouseEvent.BUTTON1) { // Left mouse button
     if (e.getID() == MouseEvent.MOUSE_PRESSED) { // Pressed down
       if (e.isShiftDown()) { // with Shift key
         // If the shift key is down, try to select a line
         int x = e.getX();
         int y = e.getY();
         // Loop through the lines checking to see if we hit one
         PolyLine selection = null;
         int numlines = lines.size();
         for (int i = 0; i < numlines; i++) {
           PolyLine line = (PolyLine) lines.get(i);
           if (line.intersects(x - 2, y - 2, 4, 4)) {
             selection = line;
             e.consume();
             break;
           }
         }
         // If we found an intersecting line, save it and repaint
         if (selection != selectedLine) { // If selection changed
           selectedLine = selection; // remember which is selected
           repaint(); // will make selection dashed
         }
       } else if (!e.isControlDown()) { // no shift key or ctrl key
         // Start a new line on mouse down without shift or ctrl
         currentLine = new PolyLine(e.getX(), e.getY());
         lines.add(currentLine);
         e.consume();
       }
     } else if (e.getID() == MouseEvent.MOUSE_RELEASED) {// Left Button Up
       // End the line on mouse up
       if (currentLine != null) {
         currentLine = null;
         e.consume();
       }
     }
   }
   // The superclass method dispatches to registered event listeners
   super.processMouseEvent(e);
 }
 /**
  * This method is called for mouse motion events. We don"t have to detect
  * gestures that initiate a drag in this method. That is the job of the
  * DragGestureRecognizer we created in the constructor: it will notify the
  * DragGestureListener defined below.
  */
 public void processMouseMotionEvent(MouseEvent e) {
   if (e.getID() == MouseEvent.MOUSE_DRAGGED && // If we"re dragging
       currentLine != null) { // and a line exists
     currentLine.addSegment(e.getX(), e.getY()); // Add a line segment
     e.consume(); // Eat the event
     repaint(); // Redisplay all lines
   }
   super.processMouseMotionEvent(e); // Invoke any listeners
 }
 /** Copy the selected line to the clipboard, then delete it */
 public void cut() {
   if (selectedLine == null)
     return; // Only works if a line is selected
   copy(); // Do a Copy operation...
   lines.remove(selectedLine); // and then erase the selected line
   selectedLine = null;
   repaint(); // Repaint because a line was removed
 }
 /** Copy the selected line to the clipboard */
 public void copy() {
   if (selectedLine == null)
     return; // Only works if a line is selected
   // Get the system Clipboard object.
   Clipboard c = this.getToolkit().getSystemClipboard();
   // Wrap the selected line in a TransferablePolyLine object
   // and pass it to the clipboard, with an object to receive notification
   // when some other application takes ownership of the clipboard
   c.setContents(new TransferablePolyLine((PolyLine) selectedLine.clone()), new ClipboardOwner() {
     public void lostOwnership(Clipboard c, Transferable t) {
       // This method is called when something else
       // is copied to the clipboard. We could use it
       // to deselect the selected line, if we wanted.
     }
   });
 }
 /** Get a PolyLine from the clipboard, if one exists, and display it */
 public void paste() {
   // Get the system Clipboard and ask for its Transferable contents
   Clipboard c = this.getToolkit().getSystemClipboard();
   Transferable t = c.getContents(this);
   // See if we can extract a PolyLine from the Transferable object
   PolyLine line;
   try {
     line = (PolyLine) t.getTransferData(TransferablePolyLine.FLAVOR);
   } catch (Exception e) { // UnsupportedFlavorException or IOException
     // If we get here, the clipboard doesn"t hold a PolyLine we can use
     getToolkit().beep(); // So beep to indicate the error
     return;
   }
   lines.add(line); // We got a line from the clipboard, so add it to list
   repaint(); // And repaint to make the line appear
 }
 /** Erase all lines and repaint. */
 public void clear() {
   lines.clear();
   repaint();
 }
 /**
  * This DragGestureListener is notified when the user initiates a drag. We
  * passed it to the DragGestureRecognizer we created in the constructor.
  */
 public DragGestureListener dragGestureListener = new DragGestureListener() {
   public void dragGestureRecognized(DragGestureEvent e) {
     // Don"t start a drag if there isn"t a selected line
     if (selectedLine == null)
       return;
     // Find out where the drag began
     MouseEvent trigger = (MouseEvent) e.getTriggerEvent();
     int x = trigger.getX();
     int y = trigger.getY();
     // Don"t do anything if the drag was not near the selected line
     if (!selectedLine.intersects(x - 4, y - 4, 8, 8))
       return;
     // Make a copy of the selected line, adjust the copy so that
     // the point under the mouse is (0,0), and wrap the copy in a
     // Tranferable wrapper.
     PolyLine copy = (PolyLine) selectedLine.clone();
     copy.translate(-x, -y);
     Transferable t = new TransferablePolyLine(copy);
     // If the system allows custom images to be dragged, make
     // an image of the line on a transparent background
     Image dragImage = null;
     Point hotspot = null;
     if (canDragImage) {
       Rectangle box = copy.getBounds();
       dragImage = createImage(box.width, box.height);
       Graphics2D g = (Graphics2D) dragImage.getGraphics();
       g.setColor(new Color(0, 0, 0, 0)); // transparent bg
       g.fillRect(0, 0, box.width, box.height);
       g.setColor(getForeground());
       g.setStroke(selectedStroke);
       g.translate(-box.x, -box.y);
       g.draw(copy);
       hotspot = new Point(-box.x, -box.y);
     }
     // Now begin dragging the line, specifying the listener
     // object to receive notifications about the progress of
     // the operation. Note: the startDrag() method is defined by
     // the event object, which is unusual.
     e.startDrag(null, // Use default drag-and-drop cursors
         dragImage, // Use the image, if supported
         hotspot, // Ditto for the image hotspot
         t, // Drag this object
         dragSourceListener); // Send notifications here
   }
 };
 /**
  * If this component is the source of a drag, then this DragSourceListener
  * will receive notifications about the progress of the drag. The only one we
  * use here is dragDropEnd() which is called after a drop occurs. We could use
  * the other methods to change cursors or perform other "drag over effects"
  */
 public DragSourceListener dragSourceListener = new DragSourceListener() {
   // Invoked when dragging stops
   public void dragDropEnd(DragSourceDropEvent e) {
     if (!e.getDropSuccess())
       return; // Ignore failed drops
     // If the drop was a move, then delete the selected line
     if (e.getDropAction() == DnDConstants.ACTION_MOVE) {
       lines.remove(selectedLine);
       selectedLine = null;
       repaint();
     }
   }
   // The following methods are unused here. We could implement them
   // to change custom cursors or perform other "drag over effects".
   public void dragEnter(DragSourceDragEvent e) {
   }
   public void dragExit(DragSourceEvent e) {
   }
   public void dragOver(DragSourceDragEvent e) {
   }
   public void dropActionChanged(DragSourceDragEvent e) {
   }
 };
 /**
  * This DropTargetListener is notified when something is dragged over this
  * component.
  */
 public DropTargetListener dropTargetListener = new DropTargetListener() {
   // This method is called when something is dragged over us.
   // If we understand what is being dragged, then tell the system
   // we can accept it, and change our border to provide extra
   // "drag under" visual feedback to the user to indicate our
   // receptivity to a drop.
   public void dragEnter(DropTargetDragEvent e) {
     if (e.isDataFlavorSupported(TransferablePolyLine.FLAVOR)) {
       e.acceptDrag(e.getDropAction());
       setBorder(canDropBorder);
     }
   }
   // Revert to our normal border if the drag moves off us.
   public void dragExit(DropTargetEvent e) {
     setBorder(normalBorder);
   }
   // This method is called when something is dropped on us.
   public void drop(DropTargetDropEvent e) {
     // If a PolyLine is dropped, accept either a COPY or a MOVE
     if (e.isDataFlavorSupported(TransferablePolyLine.FLAVOR))
       e.acceptDrop(e.getDropAction());
     else { // Otherwise, reject the drop and return
       e.rejectDrop();
       return;
     }
     // Get the dropped object and extract a PolyLine from it
     Transferable t = e.getTransferable();
     PolyLine line;
     try {
       line = (PolyLine) t.getTransferData(TransferablePolyLine.FLAVOR);
     } catch (Exception ex) { // UnsupportedFlavor or IOException
       getToolkit().beep(); // Something went wrong, so beep
       e.dropComplete(false); // Tell the system we failed
       return;
     }
     // Figure out where the drop occurred, and translate so the
     // point that was formerly (0,0) is now at that point.
     Point p = e.getLocation();
     line.translate((float) p.getX(), (float) p.getY());
     // Add the line to our list, and repaint
     lines.add(line);
     repaint();
     // Tell the system that we successfully completed the transfer.
     // This means it is safe for the initiating component to delete
     // its copy of the line
     e.dropComplete(true);
   }
   // We could provide additional drag under effects with this method.
   public void dragOver(DropTargetDragEvent e) {
   }
   // If we used custom cursors, we would update them here.
   public void dropActionChanged(DropTargetDragEvent e) {
   }
 };

} /**

* This Shape implementation represents a series of connected line segments. It
* is like a Polygon, but is not closed. This class is used by the ScribblePane
* class of the GUI chapter. It implements the Cloneable and Externalizable
* interfaces so it can be used in the Drag-and-Drop examples in the Data
* Transfer chapter.
*/

class PolyLine implements Shape, Cloneable, Externalizable {

 float x0, y0; // The starting point of the polyline.
 float[] coords; // The x and y coordinates of the end point of each line
 // segment packed into a single array for simplicity:
 // [x1,y1,x2,y2,...] Note that these are relative to x0,y0
 int numsegs; // How many line segments in this PolyLine
 // Coordinates of our bounding box, relative to (x0, y0);
 float xmin = 0f, xmax = 0f, ymin = 0f, ymax = 0f;
 // No arg constructor assumes an origin of (0,0)
 // A no-arg constructor is required for the Externalizable interface
 public PolyLine() {
   this(0f, 0f);
 }
 // The constructor.
 public PolyLine(float x0, float y0) {
   setOrigin(x0, y0); // Record the starting point.
   numsegs = 0; // Note that we have no line segments, so far
 }
 /** Set the origin of the PolyLine. Useful when moving it */
 public void setOrigin(float x0, float y0) {
   this.x0 = x0;
   this.y0 = y0;
 }
 /** Add dx and dy to the origin */
 public void translate(float dx, float dy) {
   this.x0 += dx;
   this.y0 += dy;
 }
 /**
  * Add a line segment to the PolyLine. Note that x and y are absolute
  * coordinates, even though the implementation stores them relative to x0, y0;
  */
 public void addSegment(float x, float y) {
   // Allocate or reallocate the coords[] array when necessary
   if (coords == null)
     coords = new float[32];
   if (numsegs * 2 >= coords.length) {
     float[] newcoords = new float[coords.length * 2];
     System.arraycopy(coords, 0, newcoords, 0, coords.length);
     coords = newcoords;
   }
   // Convert from absolute to relative coordinates
   x = x - x0;
   y = y - y0;
   // Store the data
   coords[numsegs * 2] = x;
   coords[numsegs * 2 + 1] = y;
   numsegs++;
   // Enlarge the bounding box, if necessary
   if (x > xmax)
     xmax = x;
   else if (x < xmin)
     xmin = x;
   if (y > ymax)
     ymax = y;
   else if (y < ymin)
     ymin = y;
 }
 /*------------------ The Shape Interface --------------------- */
 // Return floating-point bounding box
 public Rectangle2D getBounds2D() {
   return new Rectangle2D.Float(x0 + xmin, y0 + ymin, xmax - xmin, ymax - ymin);
 }
 // Return integer bounding box, rounded to outermost pixels.
 public Rectangle getBounds() {
   return new Rectangle((int) (x0 + xmin - 0.5f), // x0
       (int) (y0 + ymin - 0.5f), // y0
       (int) (xmax - xmin + 0.5f), // width
       (int) (ymax - ymin + 0.5f)); // height
 }
 // PolyLine shapes are open curves, with no interior.
 // The Shape interface says that open curves should be implicitly closed
 // for the purposes of insideness testing. For our purposes, however,
 // we define PolyLine shapes to have no interior, and the contains()
 // methods always return false.
 public boolean contains(Point2D p) {
   return false;
 }
 public boolean contains(Rectangle2D r) {
   return false;
 }
 public boolean contains(double x, double y) {
   return false;
 }
 public boolean contains(double x, double y, double w, double h) {
   return false;
 }
 // The intersects methods simply test whether any of the line segments
 // within a polyline intersects the given rectangle. Strictly speaking,
 // the Shape interface requires us to also check whether the rectangle
 // is entirely contained within the shape as well. But the contains()
 // methods for this class alwasy return false.
 // We might improve the efficiency of this method by first checking for
 // intersection with the overall bounding box to rule out cases that
 // aren"t even close.
 public boolean intersects(Rectangle2D r) {
   if (numsegs < 1)
     return false;
   float lastx = x0, lasty = y0;
   for (int i = 0; i < numsegs; i++) { // loop through the segments
     float x = coords[i * 2] + x0;
     float y = coords[i * 2 + 1] + y0;
     // See if this line segment intersects the rectangle
     if (r.intersectsLine(x, y, lastx, lasty))
       return true;
     // Otherwise move on to the next segment
     lastx = x;
     lasty = y;
   }
   return false; // No line segment intersected the rectangle
 }
 // This variant method is just defined in terms of the last.
 public boolean intersects(double x, double y, double w, double h) {
   return intersects(new Rectangle2D.Double(x, y, w, h));
 }
 // This is the key to the Shape interface; it tells Java2D how to draw
 // the shape as a series of lines and curves. We use only lines
 public PathIterator getPathIterator(final AffineTransform transform) {
   return new PathIterator() {
     int curseg = -1; // current segment
     // Copy the current segment for thread-safety, so we don"t
     // mess up of a segment is added while we"re iterating
     int numsegs = PolyLine.this.numsegs;
     public boolean isDone() {
       return curseg >= numsegs;
     }
     public void next() {
       curseg++;
     }
     // Get coordinates and type of current segment as floats
     public int currentSegment(float[] data) {
       int segtype;
       if (curseg == -1) { // First time we"re called
         data[0] = x0; // Data is the origin point
         data[1] = y0;
         segtype = SEG_MOVETO; // Returned as a moveto segment
       } else { // Otherwise, the data is a segment endpoint
         data[0] = x0 + coords[curseg * 2];
         data[1] = y0 + coords[curseg * 2 + 1];
         segtype = SEG_LINETO; // Returned as a lineto segment
       }
       // If a tranform was specified, transform point in place
       if (transform != null)
         transform.transform(data, 0, data, 0, 1);
       return segtype;
     }
     // Same as last method, but use doubles
     public int currentSegment(double[] data) {
       int segtype;
       if (curseg == -1) {
         data[0] = x0;
         data[1] = y0;
         segtype = SEG_MOVETO;
       } else {
         data[0] = x0 + coords[curseg * 2];
         data[1] = y0 + coords[curseg * 2 + 1];
         segtype = SEG_LINETO;
       }
       if (transform != null)
         transform.transform(data, 0, data, 0, 1);
       return segtype;
     }
     // This only matters for closed shapes
     public int getWindingRule() {
       return WIND_NON_ZERO;
     }
   };
 }
 // PolyLines never contain curves, so we can ignore the flatness limit
 // and implement this method in terms of the one above.
 public PathIterator getPathIterator(AffineTransform at, double flatness) {
   return getPathIterator(at);
 }
 /*------------------ Externalizable --------------------- */
 /**
  * The following two methods implement the Externalizable interface. We use
  * Externalizable instead of Seralizable so we have full control over the data
  * format, and only write out the defined coordinates
  */
 public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
   out.writeFloat(x0);
   out.writeFloat(y0);
   out.writeInt(numsegs);
   for (int i = 0; i < numsegs * 2; i++)
     out.writeFloat(coords[i]);
 }
 public void readExternal(java.io.ObjectInput in) throws java.io.IOException,
     ClassNotFoundException {
   this.x0 = in.readFloat();
   this.y0 = in.readFloat();
   this.numsegs = in.readInt();
   this.coords = new float[numsegs * 2];
   for (int i = 0; i < numsegs * 2; i++)
     coords[i] = in.readFloat();
 }
 /*------------------ Cloneable --------------------- */
 /**
  * Override the Object.clone() method so that the array gets cloned, too.
  */
 public Object clone() {
   try {
     PolyLine copy = (PolyLine) super.clone();
     if (coords != null)
       copy.coords = (float[]) this.coords.clone();
     return copy;
   } catch (CloneNotSupportedException e) {
     throw new AssertionError(); // This should never happen
   }
 }

} /*

* Copyright (c) 2004 David Flanagan. All rights reserved. This code is from the
* book Java Examples in a Nutshell, 3nd Edition. It is provided AS-IS, WITHOUT
* ANY WARRANTY either expressed or implied. You may study, use, and modify it
* for any non-commercial purpose, including teaching and use in open-source
* projects. You may distribute it non-commercially as long as you retain this
* notice. For a commercial use license, or to purchase the book, please visit
* http://www.davidflanagan.ru/javaexamples3.
*/

/**

* This class implements the Transferable interface for PolyLine objects. It
* also defines a DataFlavor used to describe this data type.
*/

class TransferablePolyLine implements Transferable {

 public static DataFlavor FLAVOR = new DataFlavor(PolyLine.class, "PolyLine");
 static DataFlavor[] FLAVORS = new DataFlavor[] { FLAVOR };
 PolyLine line; // This is the PolyLine we wrap.
 public TransferablePolyLine(PolyLine line) {
   this.line = line;
 }
 /** Return the supported flavor */
 public DataFlavor[] getTransferDataFlavors() {
   return FLAVORS;
 }
 /** Check for the one flavor we support */
 public boolean isDataFlavorSupported(DataFlavor f) {
   return f.equals(FLAVOR);
 }
 /** Return the wrapped PolyLine, if the flavor is right */
 public Object getTransferData(DataFlavor f) throws UnsupportedFlavorException {
   if (!f.equals(FLAVOR))
     throw new UnsupportedFlavorException(f);
   return line;
 }

}</source>





14. Set tree drag mode to DropMode.INSERT

   <source lang="java">

import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {

 public static void main(String args[]) {
   JFrame f = new JFrame();
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   JPanel top = new JPanel(new BorderLayout());
   JLabel dragLabel = new JLabel("Drag me:");
   JTextField text = new JTextField();
   text.setDragEnabled(true);
   top.add(dragLabel, BorderLayout.WEST);
   top.add(text, BorderLayout.CENTER);
   f.add(top, BorderLayout.NORTH);
   final JTree tree = new JTree();
   final DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
   tree.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       return dropLocation.getPath() != null;
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       TreePath path = dropLocation.getPath();
       Transferable transferable = support.getTransferable();
       String transferData;
       try {
         transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (IOException e) {
         return false;
       } catch (UnsupportedFlavorException e) {
         return false;
       }
       int childIndex = dropLocation.getChildIndex();
       if (childIndex == -1) {
         childIndex = model.getChildCount(path.getLastPathComponent());
       }
       DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData);
       DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent();
       model.insertNodeInto(newNode, parentNode, childIndex);
       TreePath newPath = path.pathByAddingChild(newNode);
       tree.makeVisible(newPath);
       tree.scrollRectToVisible(tree.getPathBounds(newPath));
       return true;
     }
   });
   JScrollPane pane = new JScrollPane(tree);
   f.add(pane, BorderLayout.CENTER);
   tree.setDropMode(DropMode.INSERT);
   f.setSize(300, 400);
   f.setVisible(true);
 }

}</source>





14. Set tree drag mode to DropMode.ON

   <source lang="java">

import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {

 public static void main(String args[]) {
   JFrame f = new JFrame();
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   JPanel top = new JPanel(new BorderLayout());
   JLabel dragLabel = new JLabel("Drag me:");
   JTextField text = new JTextField();
   text.setDragEnabled(true);
   top.add(dragLabel, BorderLayout.WEST);
   top.add(text, BorderLayout.CENTER);
   f.add(top, BorderLayout.NORTH);
   final JTree tree = new JTree();
   final DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
   tree.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       return dropLocation.getPath() != null;
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       TreePath path = dropLocation.getPath();
       Transferable transferable = support.getTransferable();
       String transferData;
       try {
         transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (IOException e) {
         return false;
       } catch (UnsupportedFlavorException e) {
         return false;
       }
       int childIndex = dropLocation.getChildIndex();
       if (childIndex == -1) {
         childIndex = model.getChildCount(path.getLastPathComponent());
       }
       DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData);
       DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent();
       model.insertNodeInto(newNode, parentNode, childIndex);
       TreePath newPath = path.pathByAddingChild(newNode);
       tree.makeVisible(newPath);
       tree.scrollRectToVisible(tree.getPathBounds(newPath));
       return true;
     }
   });
   JScrollPane pane = new JScrollPane(tree);
   f.add(pane, BorderLayout.CENTER);
   tree.setDropMode(DropMode.ON);
   f.setSize(300, 400);
   f.setVisible(true);
 }

}</source>





14. Set tree drag mode to DropMode.ON_OR_INSERT

   <source lang="java">

import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {

 public static void main(String args[]) {
   JFrame f = new JFrame();
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   JPanel top = new JPanel(new BorderLayout());
   JLabel dragLabel = new JLabel("Drag me:");
   JTextField text = new JTextField();
   text.setDragEnabled(true);
   top.add(dragLabel, BorderLayout.WEST);
   top.add(text, BorderLayout.CENTER);
   f.add(top, BorderLayout.NORTH);
   final JTree tree = new JTree();
   final DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
   tree.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       return dropLocation.getPath() != null;
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       TreePath path = dropLocation.getPath();
       Transferable transferable = support.getTransferable();
       String transferData;
       try {
         transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (IOException e) {
         return false;
       } catch (UnsupportedFlavorException e) {
         return false;
       }
       int childIndex = dropLocation.getChildIndex();
       if (childIndex == -1) {
         childIndex = model.getChildCount(path.getLastPathComponent());
       }
       DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData);
       DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent();
       model.insertNodeInto(newNode, parentNode, childIndex);
       TreePath newPath = path.pathByAddingChild(newNode);
       tree.makeVisible(newPath);
       tree.scrollRectToVisible(tree.getPathBounds(newPath));
       return true;
     }
   });
   JScrollPane pane = new JScrollPane(tree);
   f.add(pane, BorderLayout.CENTER);
   tree.setDropMode(DropMode.ON_OR_INSERT);
   f.setSize(300, 400);
   f.setVisible(true);
 }

}</source>





14. Set tree DropMode to DropMode.USE_SELECTION

   <source lang="java">

import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import javax.swing.DropMode; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DndTree {

 public static void main(String args[]) {
   JFrame f = new JFrame();
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   JPanel top = new JPanel(new BorderLayout());
   JLabel dragLabel = new JLabel("Drag me:");
   JTextField text = new JTextField();
   text.setDragEnabled(true);
   top.add(dragLabel, BorderLayout.WEST);
   top.add(text, BorderLayout.CENTER);
   f.add(top, BorderLayout.NORTH);
   final JTree tree = new JTree();
   final DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
   tree.setTransferHandler(new TransferHandler() {
     public boolean canImport(TransferHandler.TransferSupport support) {
       if (!support.isDataFlavorSupported(DataFlavor.stringFlavor) || !support.isDrop()) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       return dropLocation.getPath() != null;
     }
     public boolean importData(TransferHandler.TransferSupport support) {
       if (!canImport(support)) {
         return false;
       }
       JTree.DropLocation dropLocation = (JTree.DropLocation) support.getDropLocation();
       TreePath path = dropLocation.getPath();
       Transferable transferable = support.getTransferable();
       String transferData;
       try {
         transferData = (String) transferable.getTransferData(DataFlavor.stringFlavor);
       } catch (IOException e) {
         return false;
       } catch (UnsupportedFlavorException e) {
         return false;
       }
       int childIndex = dropLocation.getChildIndex();
       if (childIndex == -1) {
         childIndex = model.getChildCount(path.getLastPathComponent());
       }
       DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(transferData);
       DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent();
       model.insertNodeInto(newNode, parentNode, childIndex);
       TreePath newPath = path.pathByAddingChild(newNode);
       tree.makeVisible(newPath);
       tree.scrollRectToVisible(tree.getPathBounds(newPath));
       return true;
     }
   });
   JScrollPane pane = new JScrollPane(tree);
   f.add(pane, BorderLayout.CENTER);
   tree.setDropMode(DropMode.USE_SELECTION);
   f.setSize(300, 400);
   f.setVisible(true);
 }

}</source>





14. Transfer both Text and Color between JTextField and JTextArea

   <source lang="java">

import java.awt.Color; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.TransferHandler; import javax.swing.text.JTextComponent; public class DnDDemo2 {

 public static void main(String[] args) {
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(new JPanel());
   JTextField textField = new JTextField(25);
   textField.setText("Let"s swing higher");
   frame.add(textField);
   JTextArea textArea = new JTextArea("Demonstrating\ndrag and drop");
   textArea.setForeground(Color.red);
   frame.add(new JScrollPane(textArea));
   textArea.setDragEnabled(true);
   textField.setDragEnabled(true);
   TextColorTransferHandler transferHandler = new TextColorTransferHandler();
   textArea.setTransferHandler(transferHandler);
   textField.setTransferHandler(transferHandler);
   frame.pack();
   frame.setVisible(true);
 }

} class TextColorTransferHandler extends TransferHandler {

 public int getSourceActions(JComponent c) {
   return COPY_OR_MOVE;
 }
 protected Transferable createTransferable(JComponent component) {
   String text = ((JTextComponent) component).getText();
   Color color = component.getForeground();
   TextColor transferable = new TextColor(text, color);
   return transferable;
 }
 public boolean canImport(JComponent c, DataFlavor[] flavors) {
   return true;
 }
 public boolean importData(JComponent component, Transferable transferable) {
   String colorMimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=java.awt.Color";
   JTextComponent textComponent = (JTextComponent) component;
   try {
     DataFlavor colorFlavor = new DataFlavor(colorMimeType);
     Color color = (Color) transferable.getTransferData(colorFlavor);
     String text = (String) transferable.getTransferData(DataFlavor.stringFlavor);
     textComponent.setForeground(color);
     textComponent.setText(text);
   } catch (Exception e) {
     e.printStackTrace();
   }
   return true;
 }

} class TextColor implements Transferable {

 private String text;
 private Color color;
 private DataFlavor[] flavors;
 public TextColor(String text, Color color) {
   String colorMimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=java.awt.Color";
   DataFlavor colorFlavor = null;
   try {
     colorFlavor = new DataFlavor(colorMimeType);
   } catch (ClassNotFoundException e) {
   }
   flavors = new DataFlavor[2];
   flavors[0] = DataFlavor.stringFlavor;
   flavors[1] = colorFlavor;
   this.text = text;
   this.color = color;
 }
 public DataFlavor[] getTransferDataFlavors() {
   return (DataFlavor[]) flavors.clone();
 }
 public boolean isDataFlavorSupported(DataFlavor flavor) {
   for (int i = 0; i < flavors.length; i++) {
     if (flavor.equals(flavors[i])) {
       return true;
     }
   }
   return false;
 }
 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
   if (flavor.equals(flavors[0])) {
     return text;
   } else if (flavor.equals(flavors[1])) {
     return color;
   } else {
     throw new UnsupportedFlavorException(flavor);
   }
 }

} //Reference: //Java 6 New Features: A Tutorial //by Budi Kurniawan //Brainy Software Corp. 2006 //Chapter 4 - Networking //# ISBN-10: 0975212885 //# ISBN-13: 978-0975212882</source>





14. Various drop actions

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ 

/*

* DropDemo.java requires the following file:
*     ListTransferHandler.java
*/

import javax.swing.*; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*;

public class DropDemo extends JPanel implements ActionListener {

   private JComboBox dropCombo;
   private JList list;
   
   public DropDemo() {
       super(new GridLayout(2,1));
       add(createArea());
       add(createList());
   }
   
   private JPanel createList() {
       DefaultListModel listModel = new DefaultListModel();
           
       for (int i = 0; i < 10; i++) {
           listModel.addElement("List Item " + i);
       }
       
       list = new JList(listModel);
       list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
       JScrollPane scrollPane = new JScrollPane(list);
       scrollPane.setPreferredSize(new Dimension(400,100));
       
       list.setDragEnabled(true);
       list.setTransferHandler(new ListTransferHandler());
       
       dropCombo = new JComboBox(new String[] {"USE_SELECTION", "ON", "INSERT", "ON_OR_INSERT"});
       dropCombo.addActionListener(this);
       JPanel dropPanel = new JPanel();
       dropPanel.add(new JLabel("List Drop Mode:"));
       dropPanel.add(dropCombo);
       
       JPanel panel = new JPanel(new BorderLayout());
       panel.add(scrollPane, BorderLayout.CENTER);
       panel.add(dropPanel, BorderLayout.SOUTH);
       panel.setBorder(BorderFactory.createTitledBorder("List"));
       return panel;
   }
   
   private JPanel createArea() {
       String text = "Drag from or drop into this area.\nThe default action is MOVE;\nhold the Control key to COPY.";
       
       JTextArea area = new JTextArea();
       area.setText(text);
       area.setDragEnabled(true);
       JScrollPane scrollPane = new JScrollPane(area);
       scrollPane.setPreferredSize(new Dimension(400,100));
       JPanel panel = new JPanel(new BorderLayout());
       panel.add(scrollPane, BorderLayout.CENTER);
       panel.setBorder(BorderFactory.createTitledBorder("Text Area"));
       return panel;
   }
   public void actionPerformed(ActionEvent ae) {
       Object val = dropCombo.getSelectedItem();
       if (val == "USE_SELECTION") {
           list.setDropMode(DropMode.USE_SELECTION);
       } else if (val == "ON") {
           list.setDropMode(DropMode.ON);
       } else if (val == "INSERT") {
           list.setDropMode(DropMode.INSERT);
       } else if (val == "ON_OR_INSERT") {
           list.setDropMode(DropMode.ON_OR_INSERT);
       }
   }
   /**
    * Create the GUI and show it.  For thread safety,
    * this method should be invoked from the
    * event-dispatching thread.
    */
   private static void createAndShowGUI() {
       //Create and set up the window.
       JFrame frame = new JFrame("DropDemo");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       //Create and set up the content pane.
       JComponent newContentPane = new DropDemo();
       newContentPane.setOpaque(true); //content panes must be opaque
       frame.setContentPane(newContentPane);
       //Display the window.
       frame.pack();
       frame.setVisible(true);
   }
   public static void main(String[] args) {
       //Schedule a job for the event-dispatching thread:
       //creating and showing this application"s GUI.
       javax.swing.SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               //Turn off metal"s use of bold fonts
           UIManager.put("swing.boldMetal", Boolean.FALSE);
               createAndShowGUI();
           }
       });
   }

} /*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*

* ListTransferHandler.java is used by the DropDemo example.
*/

class ListTransferHandler extends TransferHandler {

 private int[] indices = null;
 private int addIndex = -1; // Location where items were added
 private int addCount = 0; // Number of items added.
 public boolean canImport(TransferHandler.TransferSupport info) {
   // Check for String flavor
   if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
     return false;
   }
   return true;
 }
 protected Transferable createTransferable(JComponent c) {
   return new StringSelection(exportString(c));
 }
 public int getSourceActions(JComponent c) {
   return TransferHandler.COPY_OR_MOVE;
 }
 public boolean importData(TransferHandler.TransferSupport info) {
   if (!info.isDrop()) {
     return false;
   }
   JList list = (JList) info.getComponent();
   DefaultListModel listModel = (DefaultListModel) list.getModel();
   JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
   int index = dl.getIndex();
   boolean insert = dl.isInsert();
   // Get the string that is being dropped.
   Transferable t = info.getTransferable();
   String data;
   try {
     data = (String) t.getTransferData(DataFlavor.stringFlavor);
   } catch (Exception e) {
     return false;
   }
   // Perform the actual import.
   if (insert) {
     listModel.add(index, data);
   } else {
     listModel.set(index, data);
   }
   return true;
 }
 protected void exportDone(JComponent c, Transferable data, int action) {
   cleanup(c, action == TransferHandler.MOVE);
 }
 // Bundle up the selected items in the list
 // as a single string, for export.
 protected String exportString(JComponent c) {
   JList list = (JList) c;
   indices = list.getSelectedIndices();
   Object[] values = list.getSelectedValues();
   StringBuffer buff = new StringBuffer();
   for (int i = 0; i < values.length; i++) {
     Object val = values[i];
     buff.append(val == null ? "" : val.toString());
     if (i != values.length - 1) {
       buff.append("\n");
     }
   }
   return buff.toString();
 }
 // Take the incoming string and wherever there is a
 // newline, break it into a separate item in the list.
 protected void importString(JComponent c, String str) {
   JList target = (JList) c;
   DefaultListModel listModel = (DefaultListModel) target.getModel();
   int index = target.getSelectedIndex();
   // Prevent the user from dropping data back on itself.
   // For example, if the user is moving items #4,#5,#6 and #7 and
   // attempts to insert the items after item #5, this would
   // be problematic when removing the original items.
   // So this is not allowed.
   if (indices != null && index >= indices[0] - 1
       && index <= indices[indices.length - 1]) {
     indices = null;
     return;
   }
   int max = listModel.getSize();
   if (index < 0) {
     index = max;
   } else {
     index++;
     if (index > max) {
       index = max;
     }
   }
   addIndex = index;
   String[] values = str.split("\n");
   addCount = values.length;
   for (int i = 0; i < values.length; i++) {
     listModel.add(index++, values[i]);
   }
 }
 // If the remove argument is true, the drop has been
 // successful and it"s time to remove the selected items
 // from the list. If the remove argument is false, it
 // was a Copy operation and the original list is left
 // intact.
 protected void cleanup(JComponent c, boolean remove) {
   if (remove && indices != null) {
     JList source = (JList) c;
     DefaultListModel model = (DefaultListModel) source.getModel();
     // If we are moving items around in the same list, we
     // need to adjust the indices accordingly, since those
     // after the insertion point have moved.
     if (addCount > 0) {
       for (int i = 0; i < indices.length; i++) {
         if (indices[i] > addIndex) {
           indices[i] += addCount;
         }
       }
     }
     for (int i = indices.length - 1; i >= 0; i--) {
       model.remove(indices[i]);
     }
   }
   indices = null;
   addCount = 0;
   addIndex = -1;
 }

}</source>