mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			655 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Java
		
	
	
	
/* TransferHandler.java --
 | 
						|
   Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
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 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.dnd.DragGestureEvent;
 | 
						|
import java.awt.dnd.DragGestureListener;
 | 
						|
import java.awt.dnd.DragGestureRecognizer;
 | 
						|
import java.awt.dnd.DragSource;
 | 
						|
import java.awt.dnd.DragSourceContext;
 | 
						|
import java.awt.dnd.DragSourceDragEvent;
 | 
						|
import java.awt.dnd.DragSourceDropEvent;
 | 
						|
import java.awt.dnd.DragSourceEvent;
 | 
						|
import java.awt.dnd.DragSourceListener;
 | 
						|
import java.awt.event.ActionEvent;
 | 
						|
import java.awt.event.InputEvent;
 | 
						|
import java.awt.event.MouseEvent;
 | 
						|
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 {@link 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);
 | 
						|
              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);
 | 
						|
 | 
						|
      if (clipboard == null)
 | 
						|
        {
 | 
						|
          // Access denied!
 | 
						|
          Toolkit.getDefaultToolkit().beep();
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
      if (command.equals(COMMAND_COPY))
 | 
						|
        transferHandler.exportToClipboard(component, clipboard, COPY);
 | 
						|
      else if (command.equals(COMMAND_CUT))
 | 
						|
        transferHandler.exportToClipboard(component, clipboard, MOVE);
 | 
						|
      else if (command.equals(COMMAND_PASTE))
 | 
						|
        {
 | 
						|
          Transferable transferable = clipboard.getContents(null);
 | 
						|
 | 
						|
          if (transferable != null)
 | 
						|
            transferHandler.importData(component, transferable);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the system cliboard or null if the caller isn't allowed to
 | 
						|
     * access the system clipboard.
 | 
						|
     *
 | 
						|
     * @param component a component, used to get the toolkit.
 | 
						|
     * @return the clipboard
 | 
						|
     */
 | 
						|
    private static Clipboard getClipboard(JComponent component)
 | 
						|
    {
 | 
						|
      try
 | 
						|
        {
 | 
						|
          return component.getToolkit().getSystemClipboard();
 | 
						|
        }
 | 
						|
      catch (SecurityException se)
 | 
						|
        {
 | 
						|
          return null;
 | 
						|
        }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  private static class SwingDragGestureRecognizer extends DragGestureRecognizer
 | 
						|
  {
 | 
						|
 | 
						|
    protected SwingDragGestureRecognizer(DragGestureListener dgl)
 | 
						|
    {
 | 
						|
      super(DragSource.getDefaultDragSource(), null, NONE, dgl);
 | 
						|
    }
 | 
						|
 | 
						|
    void gesture(JComponent c, MouseEvent e, int src, int drag)
 | 
						|
    {
 | 
						|
      setComponent(c);
 | 
						|
      setSourceActions(src);
 | 
						|
      appendEvent(e);
 | 
						|
      fireDragGestureRecognized(drag, e.getPoint());
 | 
						|
    }
 | 
						|
 | 
						|
    protected void registerListeners()
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
    protected void unregisterListeners()
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  private static class SwingDragHandler
 | 
						|
    implements DragGestureListener, DragSourceListener
 | 
						|
  {
 | 
						|
 | 
						|
    private boolean autoscrolls;
 | 
						|
 | 
						|
    public void dragGestureRecognized(DragGestureEvent e)
 | 
						|
    {
 | 
						|
      JComponent c = (JComponent) e.getComponent();
 | 
						|
      TransferHandler th = c.getTransferHandler();
 | 
						|
      Transferable t = th.createTransferable(c);
 | 
						|
      if (t != null)
 | 
						|
        {
 | 
						|
          autoscrolls = c.getAutoscrolls();
 | 
						|
          c.setAutoscrolls(false);
 | 
						|
          try
 | 
						|
            {
 | 
						|
              e.startDrag(null, t, this);
 | 
						|
              return;
 | 
						|
            }
 | 
						|
          finally
 | 
						|
            {
 | 
						|
              c.setAutoscrolls(autoscrolls);
 | 
						|
            }
 | 
						|
        }
 | 
						|
      th.exportDone(c, t, NONE);
 | 
						|
    }
 | 
						|
 | 
						|
    public void dragDropEnd(DragSourceDropEvent e)
 | 
						|
    {
 | 
						|
      DragSourceContext ctx = e.getDragSourceContext();
 | 
						|
      JComponent c = (JComponent) ctx.getComponent();
 | 
						|
      TransferHandler th = c.getTransferHandler();
 | 
						|
      if (e.getDropSuccess())
 | 
						|
        {
 | 
						|
          th.exportDone(c, ctx.getTransferable(), e.getDropAction());
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          th.exportDone(c, ctx.getTransferable(), e.getDropAction());
 | 
						|
        }
 | 
						|
      c.setAutoscrolls(autoscrolls);
 | 
						|
    }
 | 
						|
 | 
						|
    public void dragEnter(DragSourceDragEvent e)
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
    public void dragExit(DragSourceEvent e)
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
    public void dragOver(DragSourceDragEvent e)
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
    public void dropActionChanged(DragSourceDragEvent e)
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  private static final long serialVersionUID = -967749805571669910L;
 | 
						|
 | 
						|
  private static final String COMMAND_COPY = "copy";
 | 
						|
  private static final String COMMAND_CUT = "cut";
 | 
						|
  private static final String COMMAND_PASTE = "paste";
 | 
						|
 | 
						|
  public static final int NONE = 0;
 | 
						|
  public static final int COPY = 1;
 | 
						|
  public static final int MOVE = 2;
 | 
						|
  public static final int COPY_OR_MOVE = 3;
 | 
						|
 | 
						|
  private static Action copyAction = new TransferAction(COMMAND_COPY);
 | 
						|
  private static Action cutAction = new TransferAction(COMMAND_CUT);
 | 
						|
  private static Action pasteAction = new TransferAction(COMMAND_PASTE);
 | 
						|
 | 
						|
  private int sourceActions;
 | 
						|
  private Icon visualRepresentation;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The name of the property into/from which this TransferHandler
 | 
						|
   * imports/exports.
 | 
						|
   */
 | 
						|
  private String propertyName;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The DragGestureRecognizer for Swing.
 | 
						|
   */
 | 
						|
  private SwingDragGestureRecognizer recognizer;
 | 
						|
 | 
						|
  public static Action getCopyAction()
 | 
						|
  {
 | 
						|
    return copyAction;
 | 
						|
  }
 | 
						|
 | 
						|
  public static Action getCutAction()
 | 
						|
  {
 | 
						|
    return cutAction;
 | 
						|
  }
 | 
						|
 | 
						|
  public static Action getPasteAction()
 | 
						|
  {
 | 
						|
    return pasteAction;
 | 
						|
  }
 | 
						|
 | 
						|
  protected TransferHandler()
 | 
						|
  {
 | 
						|
    this.sourceActions = NONE;
 | 
						|
  }
 | 
						|
 | 
						|
  public TransferHandler(String property)
 | 
						|
  {
 | 
						|
    propertyName = property;
 | 
						|
    this.sourceActions = property != null ? COPY : NONE;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>true</code> if the data in this TransferHandler can be
 | 
						|
   * imported into the specified component. This will be the case when:
 | 
						|
   * <ul>
 | 
						|
   *   <li>The component has a readable and writable property with the property
 | 
						|
   *   name specified in the TransferHandler constructor.</li>
 | 
						|
   *   <li>There is a dataflavor with a mime type of
 | 
						|
   *     <code>application/x-java-jvm-local-object-ref</code>.</li>
 | 
						|
   *   <li>The dataflavor's representation class matches the class of the
 | 
						|
   *    property in the component.</li>
 | 
						|
   * </li>
 | 
						|
   *
 | 
						|
   * @param c the component to check
 | 
						|
   * @param flavors the possible data flavors
 | 
						|
   *
 | 
						|
   * @return <code>true</code> if the data in this TransferHandler can be
 | 
						|
   *         imported into the specified component, <code>false</code>
 | 
						|
   *         otherwise
 | 
						|
   */
 | 
						|
  public boolean canImport(JComponent c, DataFlavor[] flavors)
 | 
						|
  {
 | 
						|
    PropertyDescriptor propDesc = getPropertyDescriptor(c);
 | 
						|
    boolean canImport = false;
 | 
						|
    if (propDesc != null)
 | 
						|
      {
 | 
						|
        // Check if the property is writable. The readable check is already
 | 
						|
        // done in getPropertyDescriptor().
 | 
						|
        Method writer = propDesc.getWriteMethod();
 | 
						|
        if (writer != null)
 | 
						|
          {
 | 
						|
            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 {@link 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 {@link 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)
 | 
						|
  {
 | 
						|
    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)
 | 
						|
  {
 | 
						|
    int src = getSourceActions(c);
 | 
						|
    int drag = src & action;
 | 
						|
    if (! (e instanceof MouseEvent))
 | 
						|
      {
 | 
						|
        drag = NONE;
 | 
						|
      }
 | 
						|
    if (drag != NONE)
 | 
						|
      {
 | 
						|
        if (recognizer == null)
 | 
						|
          {
 | 
						|
            SwingDragHandler ds = new SwingDragHandler();
 | 
						|
            recognizer = new SwingDragGestureRecognizer(ds);
 | 
						|
          }
 | 
						|
        recognizer.gesture(c, (MouseEvent) e, src, drag);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        exportDone(c, null, NONE);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * 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.
 | 
						|
   *
 | 
						|
   * @param c the source component
 | 
						|
   * @param data the data that has been transferred or <code>null</code>
 | 
						|
   *        when the action is NONE
 | 
						|
   * @param action the action that has been performed
 | 
						|
   */
 | 
						|
  protected void exportDone(JComponent c, Transferable data, int action)
 | 
						|
  {
 | 
						|
    // Nothing to do in the default implementation.
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Exports the property of the component <code>c</code> that was
 | 
						|
   * specified for this TransferHandler to the clipboard, performing
 | 
						|
   * the specified action.
 | 
						|
   *
 | 
						|
   * This will check if the action is allowed by calling
 | 
						|
   * {@link #getSourceActions(JComponent)}. If the action is not allowed,
 | 
						|
   * then no export is performed.
 | 
						|
   *
 | 
						|
   * In either case the method {@link #exportDone} will be called with
 | 
						|
   * the action that has been performed, or {@link #NONE} if the action
 | 
						|
   * was not allowed or could otherwise not be completed.
 | 
						|
   * Any IllegalStateException that is thrown by the Clipboard due to
 | 
						|
   * beeing unavailable will be propagated through this method.
 | 
						|
   *
 | 
						|
   * @param c the component from which to export
 | 
						|
   * @param clip the clipboard to which the data will be exported
 | 
						|
   * @param action the action to perform
 | 
						|
   *
 | 
						|
   * @throws IllegalStateException when the clipboard is not available
 | 
						|
   */
 | 
						|
  public void exportToClipboard(JComponent c, Clipboard clip, int action)
 | 
						|
    throws IllegalStateException
 | 
						|
  {
 | 
						|
    action &= getSourceActions(c);
 | 
						|
    Transferable transferable = createTransferable(c);
 | 
						|
    if (transferable != null && action != NONE)
 | 
						|
      {
 | 
						|
        try
 | 
						|
          {
 | 
						|
            clip.setContents(transferable, null);
 | 
						|
            exportDone(c, transferable, action);
 | 
						|
          }
 | 
						|
        catch (IllegalStateException ex)
 | 
						|
          {
 | 
						|
            exportDone(c, transferable, NONE);
 | 
						|
            throw ex;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      exportDone(c, null, NONE);
 | 
						|
  }
 | 
						|
 | 
						|
  public int getSourceActions(JComponent c)
 | 
						|
  {
 | 
						|
    return sourceActions;
 | 
						|
  }
 | 
						|
 | 
						|
  public Icon getVisualRepresentation(Transferable t)
 | 
						|
  {
 | 
						|
    return visualRepresentation;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Imports the transfer data represented by <code>t</code> into the specified
 | 
						|
   * component <code>c</code> by setting the property of this TransferHandler
 | 
						|
   * on that component. If this succeeds, this method returns
 | 
						|
   * <code>true</code>, otherwise <code>false</code>.
 | 
						|
   *
 | 
						|
   *
 | 
						|
   * @param c the component to import into
 | 
						|
   * @param t the transfer data to import
 | 
						|
   *
 | 
						|
   * @return <code>true</code> if the transfer succeeds, <code>false</code>
 | 
						|
   *         otherwise
 | 
						|
   */
 | 
						|
  public boolean importData(JComponent c, Transferable t)
 | 
						|
  {
 | 
						|
    boolean ok = false;
 | 
						|
    PropertyDescriptor prop = getPropertyDescriptor(c);
 | 
						|
    if (prop != null)
 | 
						|
      {
 | 
						|
        Method writer = prop.getWriteMethod();
 | 
						|
        if (writer != null)
 | 
						|
          {
 | 
						|
            Class[] params = writer.getParameterTypes();
 | 
						|
            if (params.length == 1)
 | 
						|
              {
 | 
						|
                DataFlavor flavor = getPropertyDataFlavor(params[0],
 | 
						|
                                                   t.getTransferDataFlavors());
 | 
						|
                if (flavor != null)
 | 
						|
                  {
 | 
						|
                    try
 | 
						|
                      {
 | 
						|
                        Object value = t.getTransferData(flavor);
 | 
						|
                        writer.invoke(c, new Object[]{ value });
 | 
						|
                        ok = true;
 | 
						|
                      }
 | 
						|
                    catch (Exception ex)
 | 
						|
                      {
 | 
						|
                        // If anything goes wrong here, do nothing and return
 | 
						|
                        // false;
 | 
						|
                      }
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return ok;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the property descriptor for the property of this TransferHandler
 | 
						|
   * in the specified component, or <code>null</code> if no such property
 | 
						|
   * exists in the component. This method only returns properties that are
 | 
						|
   * at least readable (that is, it has a public no-arg getter method).
 | 
						|
   *
 | 
						|
   * @param c the component to check
 | 
						|
   *
 | 
						|
   * @return the property descriptor for the property of this TransferHandler
 | 
						|
   *         in the specified component, or <code>null</code> if no such
 | 
						|
   *         property exists in the component
 | 
						|
   */
 | 
						|
  private PropertyDescriptor getPropertyDescriptor(JComponent c)
 | 
						|
  {
 | 
						|
    PropertyDescriptor prop = null;
 | 
						|
    if (propertyName != null)
 | 
						|
      {
 | 
						|
        Class clazz = c.getClass();
 | 
						|
        BeanInfo beanInfo;
 | 
						|
        try
 | 
						|
          {
 | 
						|
            beanInfo = Introspector.getBeanInfo(clazz);
 | 
						|
          }
 | 
						|
        catch (IntrospectionException ex)
 | 
						|
          {
 | 
						|
            beanInfo = null;
 | 
						|
          }
 | 
						|
        if (beanInfo != null)
 | 
						|
          {
 | 
						|
            PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
 | 
						|
            for (int i = 0; i < props.length && prop == null; i++)
 | 
						|
              {
 | 
						|
                PropertyDescriptor desc = props[i];
 | 
						|
                if (desc.getName().equals(propertyName))
 | 
						|
                  {
 | 
						|
                    Method reader = desc.getReadMethod();
 | 
						|
                    if (reader != null)
 | 
						|
                      {
 | 
						|
                        Class[] params = reader.getParameterTypes();
 | 
						|
                        if (params == null || params.length == 0)
 | 
						|
                          prop = desc;
 | 
						|
                      }
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return prop;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Searches <code>flavors</code> to find a suitable data flavor that
 | 
						|
   * has the mime type application/x-java-jvm-local-objectref and a
 | 
						|
   * representation class that is the same as the specified <code>clazz</code>.
 | 
						|
   * When no such data flavor is found, this returns <code>null</code>.
 | 
						|
   *
 | 
						|
   * @param clazz the representation class required for the data flavor
 | 
						|
   * @param flavors the possible data flavors
 | 
						|
   *
 | 
						|
   * @return the suitable data flavor or null if none is found
 | 
						|
   */
 | 
						|
  private DataFlavor getPropertyDataFlavor(Class clazz, DataFlavor[] flavors)
 | 
						|
  {
 | 
						|
    DataFlavor found = null;
 | 
						|
    for (int i = 0; i < flavors.length && found == null; i++)
 | 
						|
      {
 | 
						|
        DataFlavor flavor = flavors[i];
 | 
						|
        if (flavor.getPrimaryType().equals("application")
 | 
						|
            && flavor.getSubType().equals("x-java-jvm-local-objectref")
 | 
						|
            && clazz.isAssignableFrom(flavor.getRepresentationClass()))
 | 
						|
          found = flavor;
 | 
						|
      }
 | 
						|
    return found;
 | 
						|
  }
 | 
						|
}
 |