import java.awt.Graphics;
import java.awt.Point;
import java.awt.dnd.*;
import java.util.*;
import javax.swing.*;

/**
 * An example of a Component that supports text drop at a particular
 * location.
 * 
 * @author  Prof. David Bernstein, James Madison University
 * @version Drop Only; Specific Location
 */
public class StringCollage extends JPanel implements DropTargetListener
{
  private static final long serialVersionUID = 1L;

  private List<StringContent>       elements;
  private Point                     dropLocation;
  
  /**
   * Default Constructor.
   */
  public StringCollage()
  {
    super();
    elements = new ArrayList<StringContent>();
    dropLocation = null;
    
    // Create a DropTarget for this Component (and make the Component
    // the DropTargetListener)
    new DropTarget(this, this);
    
    // Use a bean-oriented handler for objects with a text property
    // (i.e., with getText() and setText() methods)
    setTransferHandler(new TransferHandler("text"));
  }
  
  // Methods required to be a "text" bean
  
  /**
   * Get the text on this Component.
   * 
   * This method is required so that this is a bean with the text property.
   * 
   * @return The text of the last element
   */
  public String getText()
  {
    return elements.get(elements.size()-1).getText();
  }
  
  /**
   * Add a new piece of text to this Component.
   * 
   * If the text was dragged onto this Component it will be added at the drop
   * location. Otherwise, it won't be added. To add a new piece of text manually,
   * use the three-parameter version of this method.
   * 
   * This method is required so that this is a bean with the text property.
   * 
   * @param The text (tab delimited)
   */
  public void setText(String s)
  {
    if (dropLocation != null) setText(s, dropLocation.x, dropLocation.y);
    dropLocation = null;
    repaint();
  }

  // Methods that provide the desired GUI functionality

  /**
   * Render this Component.
   * 
   * @param g  The rendering engine to use.
   */
  public void paint(Graphics g)
  {
    super.paint(g);
    for (StringContent e: elements)
    {
      g.drawString(e.getText(), e.getLocation().x, e.getLocation().y);
    }
  }

  /**
   * Set text on this element at the given location.
   * 
   * @param text  The text to add
   * @param x     The x-coordinate
   * @param y     The y-coordinate
   */
  public void setText(String text, int x, int y)
  {
    elements.add(new StringContent(text, x, y));
  }

  // Methods required by DropTargetListener
  
  /**
   * Handle dragEnter messages.
   * 
   * @param dtde The event that generated the message
   */
  public void dragEnter(DropTargetDragEvent dtde)
  {
    dropLocation = dtde.getLocation();
  }

  /**
   * Handle dragOver messages.
   * 
   * @param dtde The event that generated the message
   */
  public void dragOver(DropTargetDragEvent dtde)
  {
    dropLocation = dtde.getLocation();
  }

  /**
   * Handle dropActionChanged messages.
   * 
   * @param dtde The event that generated the message
   */
  public void dropActionChanged(DropTargetDragEvent dtde)
  {
  }

  /**
   * Handle dragEnter messages.
   * 
   * @param dtde The event that generated the message
   */
  public void dragExit(DropTargetEvent dte)
  {
    dropLocation = null;
  }

  /**
   * Handle drop messages.
   * 
   * @param dtde The event that generated the message
   */
  public void drop(DropTargetDropEvent dtde)
  {
    // Invoke the TransferHandler object's importData() method.
    // The TransferHandler will, in turn, invoke this Component's
    // setText() method.
    TransferHandler.TransferSupport support;
    support = new TransferHandler.TransferSupport(this, dtde.getTransferable());
    getTransferHandler().importData(support);
  }
}
