Documentation Contents

# Swing Data Transfer

For the Java 2 Platform, Standard Edition, v 1.4 release, Swing has added support for data transfer between applications. A drag and drop operation is a data transfer request that has been specified by a gesture with a graphical pointing device. In the case of copy/paste, data transfer is often initiated with the keyboard. The ability to transfer data takes two forms:

- Drag and drop (DnD) support
- Clipboard transfer via cut/copy/paste

When adding data transfer support to Swing, the goal was to make it easy for developers using Swing components to add clipboard transfer as well as drag and drop to an application. Previous AWT support for drag and drop provided a great deal of flexibility, but also a fair amount of complexity, to implement. Also, AWT support for clipboard transfer had not been integrated into Swing in a natural way. For this release, data transfer support has been implemented so that the developer may take advantage of these powerful features with minimal effort.

Because the state of each Swing component is independent of the definition of the data model, it was easy to implement a mechanism for moving the data between components without worrying about the details of the data itself. The data transfer amounts to transferring part of one model to another model. (In the case of cut/copy/paste, the data is transferred between the model and the clipboard.) To support data transfer, we:

- Added a small amount of API to enable data transfer with a few method calls.
- Made it possible to disable the Swing DnD implementation so that the user can use the support provided by AWT to customize any special behavior.
- Implemented the necessary changes in the look and feel implementations we provide.

## Quick Reference: Components That Support DnD

Component | Supports Drag | Supports Drop
--- | --- | ---
`JColorChooser` | Yes | Yes
`JEditorPane` | Yes | Yes
`JFileChooser` | Yes | No
`JFormattedTextField` | Yes | Yes
`JLabel` | see here | see here
`JList` | Yes | No
`JPasswordField` | No | Yes
`JTable` | Yes | No
`JTextArea` | Yes | Yes
`JTextField` | Yes | Yes
`JTextPane` | Yes | Yes
`JTree` | Yes | No

This document has the following sections:

- Data Transfer Support
  - Default TransferHandler Support
  - Example of Adding Support to JLabel
- Drag Support
  - Default Drag Support
  - Adding Drag Support to Subclasses of Swing Classes
  - Operation of TransferHandler.exportAsDrag
- Drop Support
  - Default Drop Support
  - Using the Drop Support in Subclasses of Swing Classes
- Clipboard Transfer Support
  - Default Clipboard Transfer
  - Using the Clipboard Transfer Support in Subclasses of Swing Classes
- Implementation Details
- Changes Since Beta
- Known Bugs

## Data Transfer Support

The foundation of data transfer is support for handling the transfer of data into and out of a component. With this functionality available on the component, the mechanics of managing a drag and drop can be provided automatically. In addition, support for cut/copy/paste can also be provided automatically. The crux of this implementation is the new class `TransferHandler`. The `JComponent` property methods, `setTransferHandler` and `getTransferHandler`, provide an entrypoint to the data transfer mechanism for any component which extends `JComponent`.

The table below details the extent of the cut, copy, paste, and drop support for each of the components when a non-`null` `TransferHandler` is installed. Note that this support is enabled by the look and feel code. Support for dragging is initially disabled, but may be enabled by calling `setDragEnabled(true)` on the component. If the component doesn't have such a method, the drag may be enabled by binding some kind of gesture to it.

### Default TransferHandler Support

For the components listed below, Swing installs default implementations of `TransferHandler`. For those components that have default Swing support, the `TransferHandler` is installed by the `ComponentUI` if the value of the `transferHandler` property is `null` or marked by the presence of the `UIResource` interface. The default `TransferHandler` implementation installed by the `ComponentUI` is marked by the `UIResource` interface, enabling developers to override the default `TransferHandler`. The following table shows the support provided.

#### Components That Support DnD

Component | Exports (Drag, Cut, Copy) | Imports (Drop, Paste)
--- | --- | ---
`JColorChooser` | The selected color is offered through the JavaBeans property handling of `TransferHandler`. The flavor offered is `application/x-java-jvm-local-objectref; class=java.awt.Color`. The value transferred is determined by `getColor`. | Accepts inserts of type `Color`. The data is imported by using `setColor` (from the bean property handling). Any flavor having `class=java.awt.Color` (or a subclass of `java.awt.Color`) is accepted.
`JEditorPane` | 1.4: If the `content-type` of the `JEditorPane` is `text/plain`, the selected text is offered as `text/plain` through the `write` method of the `EditorKit`. If the `content-type` is `OTHER`, it is exported both as `text/plain` using the `getSelectedText` method, and as `OTHER` using the `write` method of the `EditorKit`. 1.4.1: The selected text, as returned by the `getSelectedText` method, is exported as `text/plain`. In addition, if the `content-type` of the `JEditorPane` is other than `text/plain`, the selected content is also offered in that other flavor using the `EditorKit`'s `write` method. | 1.4: Accepts inserts of type `text/plain` and whatever the current type returned by `getContentType`. If a type is found matching the current type (including `text/plain`), it is imported using the `EditorKit`'s `read` method. Otherwise, `text/plain` is imported through the component's `replaceSelection` method. Paste: the contents of the selection, if any, are replaced. Drop: the data is inserted at the caret position. 1.4.1: Accepts inserts of type `text/plain` and whatever the current type returned by `getContentType`. If a type is found matching the current type (excluding `text/plain`), it is imported using the `EditorKit`'s `read` method. Otherwise, `text/plain` is imported through the component's `replaceSelection` method. Paste: the contents of the selection, if any, are replaced. Drop: the data is inserted at the caret position.
`JFileChooser` | The selection is offered in the same manner as those from the native file chooser. | Imports not accepted. As the mouse is moved over the list, the potential drop point is indicated by highlighting the file/directory under the cursor. See Default Drop Support.
`JFormattedTextField` | The selected text is offered as `text/plain`. | Accepts inserts of type `text/plain`. Paste: the contents of the selection, if any, are replaced; otherwise the data is inserted at the caret position. Drop: the data is inserted at the caret position. Note that paste and drop employ the same code paths as typing from the keyboard, therefore code validation is preserved.
`JList` | If the selection is a single item, it is offered as `text/plain`. If multiple items are selected, they are offered as `text/html`. The format of the `text/html` is a `<UL>` tag followed by the selected list items each starting with an `<LI>` tag. | Imports not accepted. As the mouse is moved over the list, the potential drop point is indicated by highlighting the list item under the cursor. See Default Drop Support.
`JPasswordField` | For security reasons, cut, copy, and drag are not supported. | Accepts inserts of type `text/plain`. Paste: the contents of the selection, if any, are replaced; otherwise the data is inserted at the caret position. Drop: the data is inserted at the caret position.
`JTable` | If the selection is a single item, it is offered as `text/plain`. If multiple items are selected, they are offered as `text/html`. The format of the `text/html` is a `<TABLE>` tag followed by a `<TR>` tag for each row and a `<TD>` tag for each cell. | Imports not accepted. As the mouse is moved over the table, the potential drop point is indicated by highlighting the cell under the cursor. See Default Drop Support.
`JTextArea` | The selected text is offered as `text/plain`. | Accepts inserts of type `text/plain`. Paste: the contents of the selection, if any, are replaced; otherwise the data is inserted at the caret position. Drop: the data is inserted at the caret position.
`JTextField` | The selected text is offered as `text/plain`. | Accepts inserts of type `text/plain`. Paste: the contents of the selection, if any, are replaced; otherwise the data is inserted at the caret position. Drop: the data is inserted at the caret position.
`JTextPane` | Same as `JEditorPane`. | Same as `JEditorPane`.
`JTree` | If the selection is a single item, it is offered as `text/plain`. If multiple items are selected, they are offered as `text/html`. The format of the `text/html` is nested lists, similar to the format used for `JList`. | Imports not accepted. As the mouse is moved over the table, the potential drop point is indicated by highlighting the tree node under the cursor. See Default Drop Support.

### Example of Adding Support to `JLabel`

The `JLabel` component does not support DnD by default. The following code fragment creates a `JLabel` that supports drag and drop on the "text" property (a `String`):

    JLabel componentType = new JLabel();
    componentType.setTransferHandler(new TransferHandler("text"));
    MouseListener ml = new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            JComponent c = (JComponent)e.getSource();
            TransferHandler th = c.getTransferHandler();
            th.exportAsDrag(c, e, TransferHandler.COPY);
        }
    };
    componentType.addMouseListener(ml);

We have included a small example that implements drag and drop using a `JTextField` and a `JLabel`. You can type a value into the text field, highlight the text, then hold the mouse button down over the textfield and drag a few pixels. An icon appears under the cursor. Release the icon over the `JLabel` and see the text replace the "Drop Here" text. Simultaneously with the drop, the text is removed from the source textfield. The default behavior for drag and drop is `MOVE`. To change the behavior to `COPY`, hold down the `CONTROL` key while selecting the text. On Windows, a plus sign appears in the icon. When the text is released on the target, it is left intact in the source. You can likewise drag from the `JLabel` to the text field. Note that `JLabel` does not have bindings for copy/paste and is unable to get the focus that is required to support this feature.

See the JLabelDragNDrop.java example here.

## Drag Support

Some components, such as text fields, support selections. For those kinds of components, a drag operation is typically initiated by dragging an existing selection with the mouse. A controller for this type of component can recognize this condition and initiate a drag. For those components that don't have selections, Swing can't automatically initiate the drag, but Swing can handle the mechanics of the drag if told that a drag attempt has been initiated as shown in the `JLabel` example.

With this level of drag support, the Swing developer can focus on implementing a `TransferHandler` that represents the desired transfer, and setting properties on the Swing component. This greatly simplifies the burden to the Swing developer wanting to support dragging in an application.

Note that we are currently investigating providing different visual appearances of the drag, hence the reference to `Icon` in the API. Stay tuned for future developments.

### Default Drag Support

The simplest level of support is to set a flag that indicates the developer would like the default support enabled. The components that offer default support for dragging are described in the Exports column of the Components That Support DnD table; but to summarize, the classes that directly implement `setDragEnabled` and `getDragEnabled` are: `JColorChooser`, `JFileChooser`, `JList`, `JTable`, `JTree`, and `JTextComponent`. The drag gesture is defined as the press of the first mouse button over a selection and dragging a few pixels. Setting the `dragEnabled` property to `true` therefore has a subtle effect on mouse behavior.

When dragging is enabled on a component, the Swing controller (in the corresponding `ComponentUI` subclass) begins looking for a drag gesture, and if the `transferHandler` property is `null`, or marked by the presence of the `UIResource` interface, a default implementation is installed. The implementation provided by Swing is marked with the `UIResource` interface, so a developer can insert a new `TransferHandler` by replacing the default `TransferHandler` property with a custom implementation. When a drag gesture is recognized, the `exportAsDrag` method is called on the `TransferHandler` which initiates the drag mechanism. The actual transfer is handled by the `java.awt.dnd` mechanism, requiring no further effort from the developer.

### Adding Drag Support to Subclasses of Swing Classes

The drag support provided by Swing is activated by the `TransferHandler.exportAsDrag` method. This makes adding drag support as easy as:

1. Installing a `TransferHandler` implementation (so there is something to drag) by calling the `setTransferHandler` method.
2. Recognizing a drag gesture.
3. Calling the `exportAsDrag` method.

Some scenarios for accomplishing this are:

- Add a `MouseListener` that watches for the desired gesture, then call `getTransferHandler` on the component and call the `exportAsDrag` method when the desired gesture is found. See the JLabel example.
- Reimplement the `processMouseEvent` method in a subclass and call the `exportAsDrag` method on the ComponentUI variable when a drag gesture is seen, otherwise execute the superclass behavior.
- In a component with a custom UI implementation, have the controller call `exportAsDrag` when a drag gesture has been seen.

### Operation of TransferHandler.exportAsDrag

When the `exportAsDrag` method is called on `TransferHandler`, the drag is handled by Swing provided functionality. When this method is called, it is assumed that a valid drag gesture has been recognized. The method performs the following steps:

1. A Swing implementation of a `DragSource` and `DragListener` is used to start the drag using the `Transferable` implementation returned by `createTransferable` as data transfer object.
2. When the drop has completed, the `exportDone` method is called on the `TransferHandler`. For some operations, such as `MOVE`, it may be necessary to remove the data from the source. The default behavior for text-based components, for example, is that a standard drag implements `MOVE` behavior (following the drop the selected text is removed from the source component). The user may override this behavior by holding down the control key when the text is selected for dragging. On Windows, the drag icon visually reflects this behavior with a small plus-sign.

## Drop Support

The primary support for handling a drop is the same as for a paste operation, the `importData` method on the `TransferHandler`. The semantics of inserting data into a component are generally more meaningful at the application level than the toolkit level. Users of an application can drop all kinds of `Transferable` implementations on components that are completely unknown to the Swing toolkit. It is up to the Swing developer to provide a `TransferHandler` with meaningful import semantics if the default `TransferHandler` is insufficient.

A drop operation does have some differences from a paste however:

- Typically a potential drop site provides feedback of where the data would be accepted.
- For components with selection capabilities, the insertion point is moved to indicate where the data would be placed.

### Default Drop Support

To assist Swing developers in adding drop support to an application, Swing provides `DropTarget` implementations that use the `TransferHandler` property on the Swing component. For those components that have a non-`null` `TransferHandler` property, the drop target is installed by the `ComponentUI` if the value of the `dropTarget` property is `null` or marked by the presence of the `UIResource` interface. The default `DropTarget` implementations installed by the `ComponentUI` is marked by the `UIResource` interface, enabling developers to override the default `DropTarget`.

The components that provide a complete drop implementation by default are indicated in the Imports column of the Components That Support DnD table. There are four components that provide only some support for drop. `JFileChooser`, `JList`, `JTable`, and `JTree` by default have an installed `DropTarget` that indicates a potential insertion point. However, to fully support imports of data the developer must write and install a custom `TransferHandler`.

### Using the Drop Support in Subclasses of Swing Classes

A well behaved DropTarget implementation uses the `transferHandler` property on `JComponent` to perform the drop. The Swing developer automatically gets a simple `DropTarget` implementation that links the drop to the `TransferHandler` when the `transferHandler` property is set and the `dropTarget` property is `null`.

## Clipboard Transfer Support

Cut, copy, and paste operations perform data transfer in a manner that is more useful to those without a mouse, as they are typically initiated via a keyboard gesture. These operations can use the same `TransferHandler` services as the drag and drop support. This improves the accessibility of the data transfers, and enables Swing to provide keyboard bindings for these operations even though Swing may not know how to actually transfer the data to/from the clipboard. The keyboard bindings for clipboard transfer are dependent upon the current look and feel that is installed.

### Default Clipboard Transfer

As with drag and drop, clipboard transfers are the most useful for those components that support selections. The list of components shown in the Exports column of the Components That Support DnD table have cut, copy, and paste actions in the component action map, along with a LAF dependent set of keyboard bindings in the input map of the component. Having Swing provide these bindings frees the developer from trying to track the current look and feel and change the bindings.

### Using the Clipboard Transfer Support in Subclasses of Swing Classes

A well behaved cut, copy, and paste implementation uses the `transferHandler` property on `JComponent` to perform the transfer. When the `transferHandler` property is set on a `JComponent`, a simple `Action` implementation that links the transfer of between a `Clipboard` and `TransferHandler` is installed in the component's action map under the keys `cut`, `copy`, and `paste` if there is no action currently installed.

## Implementation Details

Note: The following information outlines private implementation details and is subject to change. We are providing this information only to satisfy the curiosity of those who have access to the source code and feel compelled to thump the tires and peek under the hood.

If a `TransferHandler` is installed on a `JComponent`, the look and feel then enables cut, copy, and paste using the following `TransferHandler` methods:

- `getCutAction`
- `getCopyAction`
- `getPasteAction`

If you bind some event to `TransferHandler.exportAsDrag` you also get drag support. This plumbing is located in package-private nested classes inside of the `TransferHandler` class.

The following package-private classes were added to the `javax.swing.plaf.basic` package for creating the default support:

`BasicTransferable`
  The basis of the various `Transferable` implementations.
`BasicDropTargetListener`
  Adds scrolling support and drop target feedback for those components supporting selection.
`BasicDragGestureRecognizer`
  Supports the "select and move a few pixels" drag gesture recognition.

Each of the `ComponentUI` classes that support DnD then have some additional nested classes:

`BasicTreeUI`:

`TreeTransferHandler`
  Default import/export support.
`TreeTransferable`
  The actual tree data.
`TreeDragGestureRecognizer`
  Tree drag gesture recognition, enabled by `JTree.setDragEnabled`.
`TreeDropHandler`
  Shows drop target location.

`BasicListUI`, `BasicTableUI`, `BasicTextUI` all have a pattern similar to as `BasicTreeUI`.

`BasicFileChooserUI`
  Uses the list support, but has a `FileTransferHandler` that produces the `FileTransferable` that extends the `ListTransferable` with the flavor used for file transfers.
`BasicColorChooserUI`
  Uses the `TransferHandler` bean support and binds the "color" property. A mouse listener is added to the preview area to bind a mouse press to the `exportAsDrag` method on the `TransferHandler`.

## Changes Since Beta

### TransferHandler Actions Should be Registered by UI

The bugtraq report that corresponds to this change is: 4460011.

To implement drag and drop, bindings were provided in the `Action` class to support copying and pasting the data. In order for a look and feel, or other code, to override these `Action`s, the UI must install them - `Action`s are no longer automatically installed by the `TransferHandler`. The package-private methods `getCutAction`, `getCopyAction`, and `getPasteAction` in `TransferHandler` are now made public.

### Ability to Disable DropTarget

The bugtraq report that corresponds to this change is: 4485914.

The drag and drop implementation causes a `DropTarget` to be added to a `JComponent` if that component has a `TransferHandler` installed. This may affect applications that are manually adding `DropTarget`s. Therefore the System property `suppressSwingDropSupport` has been added. The `JComponent` methods `setTransferHandler(TransferHandler)` and `getTransferHandler` can be used to enable or disable this property.

## Known Bugs

### Drop Clobbers Selected Text in JTextComponent

The bugtraq report that corresponds to this problem is: 4513715.

Selecting text and then dragging and dropping that text within the selected region of the same text component causes the selected text to be clobbered and nothing to be pasted. This bug is fixed in release 1.4.1.

### Occasional Errors in Restoring Caret when Exiting a Component

The bugtraq report that corresponds to this problem is: 4513720.

With the built-in drop support, Swing text components respond to DnD dragovers by setting the `Caret` to visible and using it to display the potential insert location. When the drag exits the component, the `Caret`'s visibility is restored. Unfortunately, since the `Caret` uses the same "`visible`" property to represent the usual meaning of visible as well as when it is in mid-flash, we sometimes restore the Caret's visibility incorrectly.

### Cut/Copy/Drag Broken for JEditorPane with RTFEditorKit

The bugtraq report that corresponds to this problem is: 4513638.

When using an `RTFEditorKit` set explicitly on a `JEditorPane` using `setEditorKit`, or by setting the `content-type` to `text/rtf`, cut, copy and drag no longer work. Note that this bug, filed against release 1.4, is fixed in release 1.4.1.

Copyright © 1993, 2014, Oracle and/or its affiliates. All rights reserved.
Contact Us