FileDocCategorySizeDatePackage
TransferHandler.javaAPI DocJava SE 6 API64312Tue Jun 10 00:26:42 BST 2008javax.swing

TransferHandler

public class TransferHandler extends Object implements Serializable
This class is used to handle the transfer of a Transferable to and from Swing components. The Transferable is used to represent data that is exchanged via a cut, copy, or paste to/from a clipboard. It is also used in drag-and-drop operations to represent a drag from a component, and a drop to a component. Swing provides functionality that automatically supports cut, copy, and paste keyboard bindings that use the functionality provided by an implementation of this class. Swing also provides functionality that automatically supports drag and drop that uses the functionality provided by an implementation of this class. The Swing developer can concentrate on specifying the semantics of a transfer primarily by setting the transferHandler property on a Swing component.

This class is implemented to provide a default behavior of transferring a component property simply by specifying the name of the property in the constructor. For example, to transfer the foreground color from one component to another either via the clipboard or a drag and drop operation a TransferHandler can be constructed with the string "foreground". The built in support will use the color returned by getForeground as the source of the transfer, and setForeground for the target of a transfer.

Please see How to Use Drag and Drop and Data Transfer, a section in The Java Tutorial, for more information.

author
Timothy Prinzing
author
Shannon Hickey
version
1.47 06/06/06
since
1.4

Fields Summary
public static final int
NONE
An int representing no transfer action.
public static final int
COPY
An int representing a "copy" transfer action. This value is used when data is copied to a clipboard or copied elsewhere in a drag and drop operation.
public static final int
MOVE
An int representing a "move" transfer action. This value is used when data is moved to a clipboard (i.e. a cut) or moved elsewhere in a drag and drop operation.
public static final int
COPY_OR_MOVE
An int representing a source action capability of either "copy" or "move".
public static final int
LINK
An int representing a "link" transfer action. This value is used to specify that data should be linked in a drag and drop operation.
private String
propertyName
private static SwingDragGestureRecognizer
recognizer
static final Action
cutAction
static final Action
copyAction
static final Action
pasteAction
Constructors Summary
public TransferHandler(String property)
Constructs a transfer handler that can transfer a Java Bean property from one component to another via the clipboard or a drag and drop operation.

param
property the name of the property to transfer; this can be null if there is no property associated with the transfer handler (a subclass that performs some other kind of transfer, for example)

	propertyName = property;
    
protected TransferHandler()
Convenience constructor for subclasses.

	this(null);
    
Methods Summary
public booleancanImport(javax.swing.TransferHandler$TransferSupport support)
This method is called repeatedly during a drag and drop operation to allow the developer to configure properties of, and to return the acceptability of transfers; with a return value of {@code true} indicating that the transfer represented by the given {@code TransferSupport} (which contains all of the details of the transfer) is acceptable at the current time, and a value of {@code false} rejecting the transfer.

For those components that automatically display a drop location during drag and drop, accepting the transfer, by default, tells them to show the drop location. This can be changed by calling {@code setShowDropLocation} on the {@code TransferSupport}.

By default, when the transfer is accepted, the chosen drop action is that picked by the user via their drag gesture. The developer can override this and choose a different action, from the supported source actions, by calling {@code setDropAction} on the {@code TransferSupport}.

On every call to {@code canImport}, the {@code TransferSupport} contains fresh state. As such, any properties set on it must be set on every call. Upon a drop, {@code canImport} is called one final time before calling into {@code importData}. Any state set on the {@code TransferSupport} during that last call will be available in {@code importData}.

This method is not called internally in response to paste operations. As such, it is recommended that implementations of {@code importData} explicitly call this method for such cases and that this method be prepared to return the suitability of paste operations as well.

Note: The TransferSupport object passed to this method is only valid for the duration of the method call. It is undefined what values it may contain after this method returns.

param
support the object containing the details of the transfer, not null.
return
true if the import can happen, false otherwise
throws
NullPointerException if support is {@code null}
see
#importData(TransferHandler.TransferSupport)
see
javax.swing.TransferHandler.TransferSupport#setShowDropLocation
see
javax.swing.TransferHandler.TransferSupport#setDropAction
since
1.6

        return support.getComponent() instanceof JComponent
            ? canImport((JComponent)support.getComponent(), support.getDataFlavors())
            : false;
    
public booleancanImport(javax.swing.JComponent comp, java.awt.datatransfer.DataFlavor[] transferFlavors)
Indicates whether a component will accept an import of the given set of data flavors prior to actually attempting to import it.

Note: Swing now calls the newer version of canImport that takes a TransferSupport, which in turn calls this method (only if the component in the {@code TransferSupport} is a {@code JComponent}). Developers are encouraged to call and override the newer version as it provides more information (and is the only version that supports use with a {@code TransferHandler} set directly on a {@code JFrame} or other non-{@code JComponent}).

param
comp the component to receive the transfer; provided to enable sharing of TransferHandlers
param
transferFlavors the data formats available
return
true if the data can be inserted into the component, false otherwise
see
#canImport(TransferHandler.TransferSupport)

	PropertyDescriptor prop = getPropertyDescriptor(comp);
	if (prop != null) {
	    Method writer = prop.getWriteMethod();
	    if (writer == null) {
		// read-only property. ignore
		return false;
	    }
	    Class<?>[] params = writer.getParameterTypes();
	    if (params.length != 1) {
		// zero or more than one argument, ignore
		return false;
	    }
	    DataFlavor flavor = getPropertyDataFlavor(params[0], transferFlavors);
	    if (flavor != null) {
		return true;
	    }
	}
	return false;
    
protected java.awt.datatransfer.TransferablecreateTransferable(javax.swing.JComponent c)
Creates a Transferable to use as the source for a data transfer. Returns the representation of the data to be transferred, or null if the component's property is null

param
c the component holding the data to be transferred; provided to enable sharing of TransferHandlers
return
the representation of the data to be transferred, or null if the property associated with c is null

	PropertyDescriptor property = getPropertyDescriptor(c);
	if (property != null) {
	    return new PropertyTransferable(property, c);
	}
	return null;
    
public voidexportAsDrag(javax.swing.JComponent comp, java.awt.event.InputEvent e, int action)
Causes the Swing drag support to be initiated. This is called by the various UI implementations in the javax.swing.plaf.basic package if the dragEnabled property is set on the component. This can be called by custom UI implementations to use the Swing drag support. This method can also be called by a Swing extension written as a subclass of JComponent to take advantage of the Swing drag support.

The transfer will not necessarily have been completed at the return of this call (i.e. the call does not block waiting for the drop). The transfer will take place through the Swing implementation of the java.awt.dnd mechanism, requiring no further effort from the developer. The exportDone method will be called when the transfer has completed.

param
comp the component holding the data to be transferred; provided to enable sharing of TransferHandlers
param
e the event that triggered the transfer
param
action the transfer action initially requested; either {@code COPY}, {@code MOVE} or {@code LINK}; the DnD system may change the action used during the course of the drag operation

        int srcActions = getSourceActions(comp);

        // only mouse events supported for drag operations
	if (!(e instanceof MouseEvent)
                // only support known actions
                || !(action == COPY || action == MOVE || action == LINK)
                // only support valid source actions
                || (srcActions & action) == 0) {

            action = NONE;
        }

        if (action != NONE && !GraphicsEnvironment.isHeadless()) {
	    if (recognizer == null) {
		recognizer = new SwingDragGestureRecognizer(new DragHandler());
	    }
            recognizer.gestured(comp, (MouseEvent)e, srcActions, action);
	} else {
            exportDone(comp, null, NONE);
        }
    
protected voidexportDone(javax.swing.JComponent source, java.awt.datatransfer.Transferable data, int action)
Invoked after data has been exported. This method should remove the data that was transferred if the action was MOVE.

This method is implemented to do nothing since MOVE is not a supported action of this implementation (getSourceActions does not include MOVE).

param
source the component that was the source of the data
param
data The data that was transferred or possibly null if the action is NONE.
param
action the actual action that was performed

    
public voidexportToClipboard(javax.swing.JComponent comp, java.awt.datatransfer.Clipboard clip, int action)
Causes a transfer from the given component to the given clipboard. This method is called by the default cut and copy actions registered in a component's action map.

The transfer will take place using the java.awt.datatransfer mechanism, requiring no further effort from the developer. Any data transfer will be complete and the exportDone method will be called with the action that occurred, before this method returns. Should the clipboard be unavailable when attempting to place data on it, the IllegalStateException thrown by {@link Clipboard#setContents(Transferable, ClipboardOwner)} will be propogated through this method. However, exportDone will first be called with an action of NONE for consistency.

param
comp the component holding the data to be transferred; provided to enable sharing of TransferHandlers
param
clip the clipboard to transfer the data into
param
action the transfer action requested; this should be a value of either COPY or MOVE; the operation performed is the intersection of the transfer capabilities given by getSourceActions and the requested action; the intersection may result in an action of NONE if the requested action isn't supported
throws
IllegalStateException if the clipboard is currently unavailable
see
Clipboard#setContents(Transferable, ClipboardOwner)


        if ((action == COPY || action == MOVE)
                && (getSourceActions(comp) & action) != 0) {

            Transferable t = createTransferable(comp);
            if (t != null) {
                try {
                    clip.setContents(t, null);
                    exportDone(comp, t, action);
                    return;
                } catch (IllegalStateException ise) {
                    exportDone(comp, t, NONE);
                    throw ise;
                }
            }
        }

        exportDone(comp, null, NONE);
    
public static javax.swing.ActiongetCopyAction()
Returns an {@code Action} that performs copy operations to the clipboard. When performed, this action operates on the {@code JComponent} source of the {@code ActionEvent} by invoking {@code exportToClipboard}, with a {@code COPY} action, on the component's {@code TransferHandler}.

return
an {@code Action} for performing copies to the clipboard

        return copyAction;
    
public static javax.swing.ActiongetCutAction()
Returns an {@code Action} that performs cut operations to the clipboard. When performed, this action operates on the {@code JComponent} source of the {@code ActionEvent} by invoking {@code exportToClipboard}, with a {@code MOVE} action, on the component's {@code TransferHandler}.

return
an {@code Action} for performing cuts to the clipboard

        return cutAction;
    
private static java.awt.dnd.DropTargetListenergetDropTargetListener()


        
        synchronized(DropHandler.class) {
            DropHandler handler =
                (DropHandler)AppContext.getAppContext().get(DropHandler.class);

            if (handler == null) {
                handler = new DropHandler();
                AppContext.getAppContext().put(DropHandler.class, handler);
            }

            return handler;
        }
    
public static javax.swing.ActiongetPasteAction()
Returns an {@code Action} that performs paste operations from the clipboard. When performed, this action operates on the {@code JComponent} source of the {@code ActionEvent} by invoking {@code importData}, with the clipboard contents, on the component's {@code TransferHandler}.

return
an {@code Action} for performing pastes from the clipboard

        return pasteAction;
    
private java.awt.datatransfer.DataFlavorgetPropertyDataFlavor(java.lang.Class k, java.awt.datatransfer.DataFlavor[] flavors)
Fetches the data flavor from the array of possible flavors that has data of the type represented by property type. Null is returned if there is no match.

	for(int i = 0; i < flavors.length; i++) {
	    DataFlavor flavor = flavors[i];
	    if ("application".equals(flavor.getPrimaryType()) &&
		"x-java-jvm-local-objectref".equals(flavor.getSubType()) &&
		k.isAssignableFrom(flavor.getRepresentationClass())) {

		return flavor;
	    }
	}
	return null;
    
private java.beans.PropertyDescriptorgetPropertyDescriptor(javax.swing.JComponent comp)
Fetches the property descriptor for the property assigned to this transfer handler on the given component (transfer handler may be shared). This returns null if the property descriptor can't be found or there is an error attempting to fetch the property descriptor.

	if (propertyName == null) {
	    return null;
	}
	Class<?> k = comp.getClass();
	BeanInfo bi;
	try {
	    bi = Introspector.getBeanInfo(k);
	} catch (IntrospectionException ex) {
	    return null;
	}
	PropertyDescriptor props[] = bi.getPropertyDescriptors();
	for (int i=0; i < props.length; i++) {
	    if (propertyName.equals(props[i].getName())) {
                Method reader = props[i].getReadMethod();

                if (reader != null) {
                    Class<?>[] params = reader.getParameterTypes();

                    if (params == null || params.length == 0) {
                        // found the desired descriptor
                        return props[i];
                    }
                }
	    }
	}
	return null;
    
public intgetSourceActions(javax.swing.JComponent c)
Returns the type of transfer actions supported by the source; any bitwise-OR combination of {@code COPY}, {@code MOVE} and {@code LINK}.

Some models are not mutable, so a transfer operation of {@code MOVE} should not be advertised in that case. Returning {@code NONE} disables transfers from the component.

param
c the component holding the data to be transferred; provided to enable sharing of TransferHandlers
return
{@code COPY} if the transfer property can be found, otherwise returns NONE

	PropertyDescriptor prop = getPropertyDescriptor(c);
	if (prop != null) {
	    return COPY;
	}
	return NONE;
    
public javax.swing.IcongetVisualRepresentation(java.awt.datatransfer.Transferable t)
Returns an object that establishes the look of a transfer. This is useful for both providing feedback while performing a drag operation and for representing the transfer in a clipboard implementation that has a visual appearance. The implementation of the Icon interface should not alter the graphics clip or alpha level. The icon implementation need not be rectangular or paint all of the bounding rectangle and logic that calls the icons paint method should not assume the all bits are painted. null is a valid return value for this method and indicates there is no visual representation provided. In that case, the calling logic is free to represent the transferable however it wants.

The default Swing logic will not do an alpha blended drag animation if the return is null.

param
t the data to be transferred; this value is expected to have been created by the createTransferable method
return
null, indicating there is no default visual representation

	return null;
    
public booleanimportData(javax.swing.TransferHandler$TransferSupport support)
Causes a transfer to occur from a clipboard or a drag and drop operation. The Transferable to be imported and the component to transfer to are contained within the TransferSupport.

While the drag and drop implementation calls {@code canImport} to determine the suitability of a transfer before calling this method, the implementation of paste does not. As such, it cannot be assumed that the transfer is acceptable upon a call to this method for paste. It is recommended that {@code canImport} be explicitly called to cover this case.

Note: The TransferSupport object passed to this method is only valid for the duration of the method call. It is undefined what values it may contain after this method returns.

param
support the object containing the details of the transfer, not null.
return
true if the data was inserted into the component, false otherwise
throws
NullPointerException if support is {@code null}
see
#canImport(TransferHandler.TransferSupport)
since
1.6

        return support.getComponent() instanceof JComponent
            ? importData((JComponent)support.getComponent(), support.getTransferable())
            : false;
    
public booleanimportData(javax.swing.JComponent comp, java.awt.datatransfer.Transferable t)
Causes a transfer to a component from a clipboard or a DND drop operation. The Transferable represents the data to be imported into the component.

Note: Swing now calls the newer version of importData that takes a TransferSupport, which in turn calls this method (if the component in the {@code TransferSupport} is a {@code JComponent}). Developers are encouraged to call and override the newer version as it provides more information (and is the only version that supports use with a {@code TransferHandler} set directly on a {@code JFrame} or other non-{@code JComponent}).

param
comp the component to receive the transfer; provided to enable sharing of TransferHandlers
param
t the data to import
return
true if the data was inserted into the component, false otherwise
see
#importData(TransferHandler.TransferSupport)

        PropertyDescriptor prop = getPropertyDescriptor(comp);
        if (prop != null) {
            Method writer = prop.getWriteMethod();
            if (writer == null) {
                // read-only property. ignore
                return false;
            }
            Class<?>[] params = writer.getParameterTypes();
            if (params.length != 1) {
                // zero or more than one argument, ignore
                return false;
            }
            DataFlavor flavor = getPropertyDataFlavor(params[0], t.getTransferDataFlavors());
            if (flavor != null) {
                try {
                    Object value = t.getTransferData(flavor);
                    Object[] args = { value };
                    MethodUtil.invoke(writer, comp, args);
                    return true;
                } catch (Exception ex) {
                    System.err.println("Invocation failed");
                    // invocation code
                }
            }
        }
        return false;