This implements one missing method in TransferHandler. An extensive
Mauve test accompanies this patch to show correctness.
2006-10-17 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/TransferHandler.java
(PropertyTransferable): New inner class. Handles transfers
from component properties.
(createTransferable): Implemented.
/Roman
Index: javax/swing/TransferHandler.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/TransferHandler.java,v
retrieving revision 1.16
diff -u -1 -5 -r1.16 TransferHandler.java
--- javax/swing/TransferHandler.java 16 Oct 2006 14:55:37 -0000 1.16
+++ javax/swing/TransferHandler.java 17 Oct 2006 15:25:05 -0000
@@ -32,41 +32,141 @@
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package javax.swing;
import gnu.classpath.NotImplementedException;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
+import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
public class TransferHandler implements Serializable
{
+
+ /**
+ * An implementation of [EMAIL PROTECTED] Transferable} that can be used to export
+ * data from a component's property.
+ */
+ private static class PropertyTransferable
+ implements Transferable
+ {
+ /**
+ * The component from which we export.
+ */
+ private JComponent component;
+
+ /**
+ * The property descriptor of the property that we handle.
+ */
+ private PropertyDescriptor property;
+
+ /**
+ * Creates a new PropertyTransferable.
+ *
+ * @param c the component from which we export
+ * @param prop the property from which we export
+ */
+ PropertyTransferable(JComponent c, PropertyDescriptor prop)
+ {
+ component = c;
+ property = prop;
+ }
+
+ /**
+ * Returns the data flavors supported by the Transferable.
+ *
+ * @return the data flavors supported by the Transferable
+ */
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ DataFlavor[] flavors;
+ Class propClass = property.getPropertyType();
+ String mime = DataFlavor.javaJVMLocalObjectMimeType + "; class="
+ + propClass.getName();
+ try
+ {
+ DataFlavor flavor = new DataFlavor(mime);
+ flavors = new DataFlavor[]{ flavor };
+ }
+ catch (ClassNotFoundException ex)
+ {
+ flavors = new DataFlavor[0];
+ }
+ return flavors;
+ }
+
+ /**
+ * Returns <code>true</code> when the specified data flavor is supported,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when the specified data flavor is supported,
+ * <code>false</code> otherwise
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ Class propClass = property.getPropertyType();
+ return flavor.getPrimaryType().equals("application")
+ && flavor.getSubType().equals("x-java-jvm-local-objectref")
+ && propClass.isAssignableFrom(flavor.getRepresentationClass());
+ }
+
+ /**
+ * Returns the actual transfer data.
+ *
+ * @param flavor the data flavor
+ *
+ * @return the actual transfer data
+ */
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException
+ {
+ if (isDataFlavorSupported(flavor))
+ {
+ Method getter = property.getReadMethod();
+ Object o;
+ try
+ {
+ o = getter.invoke(component, null);
+ return o;
+ }
+ catch (Exception ex)
+ {
+ throw new IOException("Property read failed: "
+ + property.getName());
+ }
+ }
+ else
+ throw new UnsupportedFlavorException(flavor);
+ }
+ }
+
static class TransferAction extends AbstractAction
{
private String command;
public TransferAction(String command)
{
super(command);
this.command = command;
}
public void actionPerformed(ActionEvent event)
{
JComponent component = (JComponent) event.getSource();
TransferHandler transferHandler = component.getTransferHandler();
Clipboard clipboard = getClipboard(component);
@@ -193,34 +293,54 @@
{
Class[] params = writer.getParameterTypes();
if (params.length == 1)
{
// Number of parameters ok, now check mime type and
// representation class.
DataFlavor flavor = getPropertyDataFlavor(params[0], flavors);
if (flavor != null)
canImport = true;
}
}
}
return canImport;
}
+ /**
+ * Creates a [EMAIL PROTECTED] Transferable} that can be used to export data
+ * from the specified component.
+ *
+ * This method returns <code>null</code> when the specified component
+ * doesn't have a readable property that matches the property name
+ * specified in the <code>TransferHandler</code> constructor.
+ *
+ * @param c the component to create a transferable for
+ *
+ * @return a [EMAIL PROTECTED] Transferable} that can be used to export data
+ * from the specified component, or null if the component doesn't
+ * have a readable property like the transfer handler
+ */
protected Transferable createTransferable(JComponent c)
- throws NotImplementedException
{
- return null;
+ Transferable transferable = null;
+ if (propertyName != null)
+ {
+ PropertyDescriptor prop = getPropertyDescriptor(c);
+ if (prop != null)
+ transferable = new PropertyTransferable(c, prop);
+ }
+ return transferable;
}
public void exportAsDrag(JComponent c, InputEvent e, int action)
throws NotImplementedException
{
// TODO: Implement this properly
}
/**
* This method is invoked after data has been exported.
* Subclasses should implement this method to remove the data that has been
* transferred when the action was <code>MOVE</code>.
*
* The default implementation does nothing because MOVE is not supported.
*